LCOV - code coverage report
Current view: top level - star/private - adjust_mesh_split_merge.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 787 0
Test Date: 2025-05-08 18:23:42 Functions: 0.0 % 18 0

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2016-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_mesh_split_merge
      21              : 
      22              :       use star_private_def
      23              :       use const_def, only: dp, ln10, pi4, four_thirds_pi
      24              :       use chem_def, only: ih1, ihe3, ihe4
      25              :       use utils_lib
      26              :       use auto_diff_support
      27              : 
      28              :       implicit none
      29              : 
      30              :       private
      31              :       public :: remesh_split_merge
      32              : 
      33              :       contains
      34              : 
      35              :       ! makes new mesh and sets new values for xh and xa.
      36            0 :       integer function remesh_split_merge(s)
      37              :          use star_utils, only: total_angular_momentum, set_dm_bar
      38              : 
      39              :          type (star_info), pointer :: s
      40            0 :          real(dp) :: old_J, new_J
      41              :          integer :: ierr
      42              : 
      43              :          include 'formats'
      44              : 
      45            0 :          if (s% RSP2_flag) then
      46            0 :             call mesa_error(__FILE__,__LINE__,'need to add mlt_vc and Hp_face to remesh_split_merge')
      47              :          end if
      48              : 
      49            0 :          s% amr_split_merge_has_undergone_remesh(:) = .false.
      50              : 
      51            0 :          remesh_split_merge = keep_going
      52            0 :          if (.not. s% okay_to_remesh) return
      53              : 
      54            0 :          if (s% rotation_flag) old_J = total_angular_momentum(s)
      55              : 
      56            0 :          call amr(s,ierr)
      57            0 :          if (ierr /= 0) then
      58            0 :             s% retry_message = 'remesh_split_merge failed'
      59            0 :             if (s% report_ierr) write(*, *) s% retry_message
      60            0 :             s% result_reason = adjust_mesh_failed
      61            0 :             s% termination_code = t_adjust_mesh_failed
      62            0 :             remesh_split_merge = terminate
      63            0 :             return
      64              :          end if
      65              : 
      66            0 :          call set_dm_bar(s, s% nz, s% dm, s% dm_bar)
      67              : 
      68            0 :          if (s% rotation_flag) then
      69            0 :             new_J = total_angular_momentum(s)
      70            0 :             if (abs((old_J-new_J)/old_J)>1d-14) then
      71            0 :                write(*,*) "Error in angular momemtum conservation from amr split merge"
      72            0 :                s% result_reason = adjust_mesh_failed
      73            0 :                s% termination_code = t_adjust_mesh_failed
      74            0 :                remesh_split_merge = terminate
      75            0 :                return
      76              :             end if
      77              :          end if
      78              : 
      79            0 :       end function remesh_split_merge
      80              : 
      81              : 
      82            0 :       subroutine amr(s,ierr)
      83            0 :          use hydro_rotation, only: w_div_w_roche_jrot, update1_i_rot_from_xh
      84              :          use star_utils, only: get_r_from_xh
      85              :          type (star_info), pointer :: s
      86              :          integer, intent(out) :: ierr
      87            0 :          real(dp) :: TooBig, TooSmall, MaxTooBig, MaxTooSmall
      88            0 :          real(dp) :: grad_xa(s% species), new_xa(s% species), &
      89            0 :             tau_center, r00
      90              :          integer :: iTooBig, iTooSmall, iter, k, species, &
      91              :             nz, num_split, num_merge, nz_old
      92              :          include 'formats'
      93            0 :          species = s% species
      94            0 :          nz_old = s% nz
      95            0 :          ierr = 0
      96            0 :          num_split = 0
      97            0 :          num_merge = 0
      98            0 :          MaxTooSmall = s% split_merge_amr_MaxShort
      99            0 :          MaxTooBig = s% split_merge_amr_MaxLong
     100            0 :          k = nz_old
     101              :          tau_center = s% tau(k) + &
     102            0 :             s% dm(k)*s% opacity(k)/(pi4*s% rmid(k)*s% rmid(k))
     103            0 :          do iter = 1, s% split_merge_amr_max_iters
     104              :             call biggest_smallest(s, tau_center, TooBig, TooSmall, iTooBig, iTooSmall)
     105            0 :             if (mod(iter,2) == 0) then
     106            0 :                if (iTooSmall > 0 .and. TooSmall > MaxTooSmall) then
     107            0 :                   call split1
     108            0 :                else if (iTooBig > 0 .and. TooBig > MaxTooBig) then
     109            0 :                   call merge1
     110              :                else
     111              :                   exit
     112              :                end if
     113              :             else
     114            0 :                if (iTooBig > 0 .and. TooBig > MaxTooBig) then
     115            0 :                   call merge1
     116            0 :                else if (iTooSmall > 0 .and. TooSmall > MaxTooSmall) then
     117            0 :                   call split1
     118              :                else
     119              :                   exit
     120              :                end if
     121              :             end if
     122            0 :             if (ierr /= 0) return
     123              :          end do
     124            0 :          do iter = 1, 100
     125              :             call emergency_merge(s, iTooSmall)
     126            0 :             if (iTooSmall == 0) exit
     127            0 :             if (s% split_merge_amr_avoid_repeated_remesh .and. &
     128              :                   s% amr_split_merge_has_undergone_remesh(iTooSmall)) exit
     129            0 :             if (s% trace_split_merge_amr) &
     130            0 :                write(*,2) 'emergency_merge', iTooSmall, s% dq(iTooSmall)
     131            0 :             call do_merge(s, iTooSmall, species, new_xa, ierr)
     132            0 :             if (ierr /= 0) return
     133            0 :             num_merge = num_merge + 1
     134            0 :             if (s% trace_split_merge_amr) then
     135            0 :                call report_energies(s,'after emergency_merge')
     136              :                !write(*,*)
     137              :             end if
     138              :          end do
     139            0 :          do iter = 1, 100
     140              :             call emergency_split(s, iTooBig)
     141            0 :             if (iTooBig == 0) exit
     142            0 :             if (s% split_merge_amr_avoid_repeated_remesh .and. &
     143              :                   s% amr_split_merge_has_undergone_remesh(iTooBig)) exit
     144            0 :             if (s% trace_split_merge_amr) &
     145            0 :                write(*,2) 'emergency_split', iTooBig, s% dq(iTooBig)
     146            0 :             call do_split(s, iTooBig, species, tau_center, grad_xa, new_xa, ierr)
     147            0 :             if (ierr /= 0) return
     148            0 :             num_split = num_split + 1
     149            0 :             if (s% trace_split_merge_amr) then
     150            0 :                call report_energies(s,'after emergency_split')
     151              :                !write(*,*)
     152              :             end if
     153              :          end do
     154            0 :          s% mesh_call_number = s% mesh_call_number + 1
     155            0 :          nz = s% nz
     156            0 :          s% q(nz) = s% dq(nz)
     157            0 :          s% m(nz) = s% dm(nz) + s% m_center
     158            0 :          if (s% show_mesh_changes) then
     159            0 :             write(*,*) 'doing mesh_call_number', s% mesh_call_number
     160            0 :             write(*,*) '                nz_old', nz_old
     161            0 :             write(*,*) '                nz_new', nz
     162            0 :             write(*,*) '                 split', num_split
     163            0 :             write(*,*) '                merged', num_merge
     164              :          end if
     165            0 :          if (s% rotation_flag) then  !update moments of inertia and omega
     166            0 :             do k=1, s% nz
     167            0 :                r00 = get_r_from_xh(s,k)
     168              :                s% w_div_w_crit_roche(k) = &
     169              :                   w_div_w_roche_jrot(r00,s% m(k),s% j_rot(k),s% cgrav(k), &
     170            0 :                   s% w_div_wcrit_max, s% w_div_wcrit_max2, s% w_div_wc_flag)
     171            0 :                call update1_i_rot_from_xh(s, k)
     172            0 :                s% omega(k) = s% j_rot(k)/s% i_rot(k)% val
     173              :             end do
     174              :          end if
     175            0 :          if (s% model_number == -6918) call mesa_error(__FILE__,__LINE__,'amr')
     176              : 
     177              :          contains
     178              : 
     179            0 :          subroutine split1  ! ratio of desired/actual is too large
     180              :             include 'formats'
     181            0 :             if (s% trace_split_merge_amr) then
     182            0 :                write(*,4) 'do_merge TooSmall', &
     183            0 :                   iTooSmall, s% nz, s% model_number, &
     184            0 :                   TooSmall, MaxTooSmall, s% dq(iTooSmall)
     185            0 :                call report_energies(s,'before merge TooSmall')
     186              :             end if
     187            0 :             call do_merge(s, iTooSmall, species, new_xa, ierr)
     188            0 :             if (ierr /= 0) return
     189            0 :             num_merge = num_merge + 1
     190            0 :             if (s% trace_split_merge_amr) then
     191            0 :                call report_energies(s,'after merge')
     192              :                !write(*,*)
     193              :             end if
     194            0 :          end subroutine split1
     195              : 
     196            0 :          subroutine merge1  ! ratio of actual/desired is too large
     197              :             include 'formats'
     198            0 :             if (s% trace_split_merge_amr) then
     199            0 :                write(*,4) 'do_split TooBig', iTooBig, &
     200            0 :                   s% nz, s% model_number, TooBig, MaxTooBig, s% dq(iTooBig)
     201            0 :                call report_energies(s,'before split')
     202              :             end if
     203            0 :             call do_split(s, iTooBig, species, tau_center, grad_xa, new_xa, ierr)
     204            0 :             if (ierr /= 0) return
     205            0 :             num_split = num_split + 1
     206            0 :             if (s% trace_split_merge_amr) then
     207            0 :                call report_energies(s,'after split')
     208              :                !write(*,*)
     209              :             end if
     210              :          end subroutine merge1
     211              : 
     212              :       end subroutine amr
     213              : 
     214              : 
     215            0 :       subroutine emergency_merge(s, iTooSmall)
     216              :          type (star_info), pointer :: s
     217              :          integer, intent(out) :: iTooSmall
     218              :          integer :: k_min_dq
     219              :          include 'formats'
     220            0 :          k_min_dq = minloc(s% dq(1:s% nz),dim=1)
     221            0 :          if (s% dq(k_min_dq) < s% split_merge_amr_dq_min) then
     222            0 :             iTooSmall = k_min_dq
     223              :          else
     224            0 :             iTooSmall = 0
     225              :          end if
     226            0 :       end subroutine emergency_merge
     227              : 
     228              : 
     229            0 :       subroutine emergency_split(s, iTooBig)
     230              :          type (star_info), pointer :: s
     231              :          integer, intent(out) :: iTooBig
     232              :          integer :: k_max_dq
     233              :          include 'formats'
     234            0 :          k_max_dq = maxloc(s% dq(1:s% nz),dim=1)
     235            0 :          if (s% dq(k_max_dq) > s% split_merge_amr_dq_max) then
     236            0 :             iTooBig = k_max_dq
     237              :          else
     238            0 :             iTooBig = 0
     239              :          end if
     240            0 :       end subroutine emergency_split
     241              : 
     242              : 
     243            0 :       subroutine biggest_smallest( &
     244              :             s, tau_center, TooBig, TooSmall, iTooBig, iTooSmall)
     245              :          type (star_info), pointer :: s
     246              :          real(dp), intent(in) :: tau_center
     247              :          real(dp), intent(out) :: TooBig, TooSmall
     248              :          integer, intent(out) :: iTooBig, iTooSmall
     249              :          real(dp) :: &
     250            0 :             oversize_ratio, undersize_ratio, abs_du_div_cs, &
     251            0 :             xmin, xmax, dx_actual, xR, xL, dq_min, dq_max, dx_baseline, &
     252            0 :             outer_dx_baseline, inner_dx_baseline, inner_outer_q, r_core_cm, &
     253            0 :             target_dr_core, target_dlnR_envelope, target_dlnR_core, target_dr_envelope
     254              :          logical :: hydrid_zoning, flipped_hydrid_zoning, log_zoning, logtau_zoning, &
     255              :             du_div_cs_limit_flag
     256              :          integer :: nz, nz_baseline, k, nz_r_core
     257            0 :          real(dp), pointer :: v(:), r_for_v(:)
     258              : 
     259              :          include 'formats'
     260              : 
     261            0 :          nz = s% nz
     262            0 :          hydrid_zoning = s% split_merge_amr_hybrid_zoning
     263            0 :          flipped_hydrid_zoning = s% split_merge_amr_flipped_hybrid_zoning
     264            0 :          log_zoning = s% split_merge_amr_log_zoning
     265            0 :          logtau_zoning = s% split_merge_amr_logtau_zoning
     266            0 :          nz_baseline = s% split_merge_amr_nz_baseline
     267            0 :          nz_r_core = s% split_merge_amr_nz_r_core
     268            0 :          if (s% split_merge_amr_mesh_delta_coeff /= 1d0) then
     269            0 :             nz_baseline = int(dble(nz_baseline)/s% split_merge_amr_mesh_delta_coeff)
     270            0 :             nz_r_core = int(dble(nz_r_core)/s% split_merge_amr_mesh_delta_coeff)
     271              :          end if
     272            0 :          if (s% split_merge_amr_r_core_cm > 0d0) then
     273              :             r_core_cm = s% split_merge_amr_r_core_cm
     274            0 :          else if (s% split_merge_amr_nz_r_core_fraction > 0d0) then
     275              :             r_core_cm = s% R_center + &
     276            0 :                s% split_merge_amr_nz_r_core_fraction*(s% r(1) - s% R_center)
     277              :          else
     278            0 :             r_core_cm = s% R_center
     279              :          end if
     280            0 :          dq_min = s% split_merge_amr_dq_min
     281            0 :          dq_max = s% split_merge_amr_dq_max
     282            0 :          inner_outer_q = 0d0
     283            0 :          if (s% u_flag) then
     284            0 :             v => s% u
     285            0 :             r_for_v => s% rmid
     286            0 :          else if (s% v_flag) then
     287            0 :             v => s% v
     288            0 :             r_for_v => s% r
     289              :          else
     290            0 :             nullify(v,r_for_v)
     291              :          end if
     292              : 
     293            0 :          if (hydrid_zoning) then
     294            0 :             target_dr_core = (r_core_cm - s% R_center)/nz_r_core
     295              :             target_dlnR_envelope = &
     296            0 :                (s% lnR(1) - log(max(1d0,r_core_cm)))/(nz_baseline - nz_r_core)
     297            0 :          else if (flipped_hydrid_zoning) then
     298            0 :             target_dlnR_core = (log(max(1d0,r_core_cm)) - s% R_center)/(nz_baseline - nz_r_core)
     299            0 :             target_dr_envelope = (s% r(1) - r_core_cm)/nz_r_core
     300            0 :          else if (logtau_zoning) then
     301              :             k = nz
     302            0 :             xmin = log(tau_center)
     303            0 :             xmax = log(s% tau(1))
     304            0 :             inner_dx_baseline = (xmin - xmax)/nz_baseline  ! keep it > 0
     305            0 :             outer_dx_baseline = inner_dx_baseline
     306            0 :          else if (log_zoning) then
     307            0 :             xmin = log(max(1d0,s% R_center))
     308            0 :             xmax = s% lnR(1)
     309            0 :             inner_dx_baseline = (xmax - xmin)/nz_baseline
     310            0 :             outer_dx_baseline = inner_dx_baseline
     311              :          else
     312            0 :             xmin = s% R_center
     313            0 :             xmax = s% r(1)
     314            0 :             inner_dx_baseline = (xmax - xmin)/nz_baseline
     315            0 :             outer_dx_baseline = inner_dx_baseline
     316              :          end if
     317            0 :          dx_baseline = outer_dx_baseline
     318              : 
     319            0 :          TooBig = 0d0
     320            0 :          TooSmall = 0d0
     321            0 :          iTooBig = -1
     322            0 :          iTooSmall = -1
     323            0 :          xR = xmin  ! start at center
     324            0 :          do k = nz, 1, -1
     325              : 
     326            0 :             xL = xR
     327            0 :             dx_baseline = inner_dx_baseline
     328            0 :             if (hydrid_zoning) then
     329            0 :                if (s% r(k) < r_core_cm) then
     330            0 :                   xR = s% r(k)
     331            0 :                   if (k == nz) then
     332            0 :                      xL = s% R_center
     333              :                   else
     334            0 :                      xL = s% r(k+1)
     335              :                   end if
     336              :                   dx_baseline = target_dr_core
     337              :                else
     338            0 :                   xR = log(s% r(k))
     339            0 :                   if (k == nz) then
     340            0 :                      xL = log(max(1d0,s% R_center))
     341              :                   else
     342            0 :                      xL = log(s% r(k+1))
     343              :                   end if
     344              :                   dx_baseline = target_dlnR_envelope
     345              :                end if
     346            0 :             else if (flipped_hydrid_zoning) then
     347            0 :                if (s% r(k) <= r_core_cm) then
     348            0 :                   xR = log(s% r(k))
     349            0 :                   if (k == nz) then
     350            0 :                      xL = log(max(1d0,s% R_center))
     351              :                   else
     352            0 :                      xL = log(s% r(k+1))
     353              :                   end if
     354              :                   dx_baseline = target_dlnR_core
     355              :                else
     356            0 :                   xR = s% r(k)
     357            0 :                   if (k == nz) then
     358            0 :                      xL = s% R_center
     359              :                   else
     360            0 :                      xL = s% r(k+1)
     361              :                   end if
     362              :                   dx_baseline = target_dr_core
     363              :                end if
     364            0 :             else if (logtau_zoning) then
     365            0 :                xR = log(s% tau(k))
     366            0 :             else if (log_zoning) then
     367            0 :                xR = log(s% r(k))  ! s% lnR(k) may not be set since making many changes
     368              :             else
     369            0 :                xR = s% r(k)
     370              :             end if
     371              : 
     372            0 :             if (s% split_merge_amr_avoid_repeated_remesh .and. &
     373              :                   (s% split_merge_amr_avoid_repeated_remesh .and. &
     374              :                      s% amr_split_merge_has_undergone_remesh(k))) cycle
     375            0 :             dx_actual = xR - xL
     376            0 :             if (logtau_zoning) dx_actual = -dx_actual  ! make dx_actual > 0
     377              : 
     378              :             ! first check for cells that are too big and need to be split
     379            0 :             oversize_ratio = dx_actual/dx_baseline
     380            0 :             if (TooBig < oversize_ratio .and. s% dq(k) > 5d0*dq_min) then
     381            0 :                if (k < nz .or. s% split_merge_amr_okay_to_split_nz) then
     382            0 :                   if (k > 1 .or. s% split_merge_amr_okay_to_split_1) then
     383            0 :                      TooBig = oversize_ratio; iTooBig = k
     384              :                   end if
     385              :                end if
     386              :             end if
     387              : 
     388              :             ! next check for cells that are too small and need to be merged
     389              : 
     390            0 :             if (s% merge_amr_ignore_surface_cells .and. &
     391              :                   k<=s% merge_amr_k_for_ignore_surface_cells) cycle
     392              : 
     393            0 :             if (abs(dx_actual)>0d0) then
     394            0 :                undersize_ratio = max(dx_baseline/dx_actual, dq_min/s% dq(k))
     395              :             else
     396            0 :                undersize_ratio = dq_min/s% dq(k)
     397              :             end if
     398              : 
     399            0 :             if (s% merge_amr_max_abs_du_div_cs >= 0d0) then
     400            0 :                call check_merge_limits
     401            0 :             else if (TooSmall < undersize_ratio .and. s% dq(k) < dq_max/5d0) then
     402            0 :                TooSmall = undersize_ratio; iTooSmall = k
     403              :             end if
     404              : 
     405              :          end do
     406              : 
     407              : 
     408              :          contains
     409              : 
     410            0 :          subroutine check_merge_limits
     411              :             ! Pablo's additions to modify when merge
     412              :             ! merge_amr_max_abs_du_div_cs
     413              :             ! merge_amr_du_div_cs_limit_only_for_compression
     414              :             ! merge_amr_inhibit_at_jumps
     415              : 
     416            0 :             du_div_cs_limit_flag = .false.
     417              : 
     418            0 :             if (.not. s% merge_amr_du_div_cs_limit_only_for_compression) then
     419            0 :                du_div_cs_limit_flag = .true.
     420            0 :             else if (associated(v)) then
     421            0 :                if (k < nz) then
     422            0 :                   if (v(k+1)*pow2(r_for_v(k+1)) > v(k)*pow2(r_for_v(k))) then
     423            0 :                      du_div_cs_limit_flag = .true.
     424              :                   end if
     425              :                end if
     426            0 :                if (.not. du_div_cs_limit_flag .and. k > 1) then
     427            0 :                   if (v(k)*pow2(r_for_v(k)) > v(k-1)*pow2(r_for_v(k-1))) then
     428            0 :                      du_div_cs_limit_flag = .true.
     429              :                   end if
     430              :                end if
     431              :             end if
     432              : 
     433            0 :             if (du_div_cs_limit_flag .and. associated(v)) then
     434            0 :                if (k == 1) then
     435            0 :                   abs_du_div_cs = abs(v(k) - v(k+1))/s% csound(k)
     436            0 :                else if (k == nz) then
     437            0 :                   abs_du_div_cs = abs(v(nz-1) - v(nz))/s% csound(nz)
     438              :                else
     439              :                   abs_du_div_cs = max(abs(v(k) - v(k+1)), &
     440            0 :                             abs(v(k) - v(k-1)))/s% csound(k)
     441              :                end if
     442              :             else
     443            0 :                abs_du_div_cs = 0d0
     444              :             end if
     445              : 
     446            0 :             if (du_div_cs_limit_flag) then
     447            0 :                if (s% merge_amr_inhibit_at_jumps) then
     448              :                   ! reduce undersize_ratio for large jumps
     449              :                   ! i.e. large jumps inhibit merges but don't prohibit completely
     450            0 :                   if (abs_du_div_cs > s% merge_amr_max_abs_du_div_cs) &
     451              :                      undersize_ratio = undersize_ratio * &
     452            0 :                         s% merge_amr_max_abs_du_div_cs/abs_du_div_cs
     453            0 :                   if (TooSmall < undersize_ratio .and. s% dq(k) < dq_max/5d0) then  ! switch
     454            0 :                      TooSmall = undersize_ratio; iTooSmall = k
     455              :                   end if
     456              :                else if (TooSmall < undersize_ratio .and. &
     457            0 :                         abs_du_div_cs <= s% merge_amr_max_abs_du_div_cs .and. &
     458              :                         s% dq(k) < dq_max/5d0) then
     459            0 :                   TooSmall = undersize_ratio; iTooSmall = k
     460              :                end if
     461              :             else
     462            0 :                if (TooSmall < undersize_ratio .and. s% dq(k) < dq_max/5d0) then
     463            0 :                   TooSmall = undersize_ratio; iTooSmall = k
     464              :                end if
     465              :             end if
     466            0 :          end subroutine check_merge_limits
     467              : 
     468              : 
     469              :       end subroutine biggest_smallest
     470              : 
     471              : 
     472            0 :       subroutine do_merge(s, i_merge, species, new_xa, ierr)
     473              :          use mesh_adjust, only: set_lnT_for_energy
     474              :          use star_utils, only: set_rmid
     475              :          type (star_info), pointer :: s
     476              :          integer, intent(in) :: i_merge, species
     477              :          real(dp), intent(inout) :: new_xa(species)
     478              :          integer, intent(out) :: ierr
     479              :          logical :: merge_center
     480              :          integer :: i, ip, i0, im, q, nz, qi_max, qim_max
     481              :          real(dp) :: &
     482            0 :             drR, drL, v, &
     483            0 :             dm, dm_i, dm_ip, star_PE0, star_PE1, &
     484            0 :             cell_ie, cell_etrb, &
     485            0 :             Esum_i, KE_i, PE_i, IE_i, Etrb_i, &
     486            0 :             Esum_ip, KE_ip, PE_ip, IE_ip, Etrb_ip, &
     487            0 :             KE, &
     488            0 :             j_rot_new, j_rot_p1_new, J_old, &
     489            0 :             dmbar_old, dmbar_p1_old, dmbar_p2_old, &
     490            0 :             dmbar_new, dmbar_p1_new
     491              :          include 'formats'
     492              : 
     493            0 :          ierr = 0
     494            0 :          s% need_to_setvars = .true.
     495            0 :          star_PE0 = get_star_PE(s)
     496            0 :          nz = s% nz
     497              : 
     498            0 :          i = i_merge
     499              : 
     500            0 :          s% num_hydro_merges = s% num_hydro_merges+1
     501            0 :          if (i > 1 .and. i < s% nz) then
     502              :             ! don't merge across change in most abundance species
     503            0 :             qi_max = maxloc(s% xa(1:species,i), dim=1)
     504            0 :             qim_max = maxloc(s% xa(1:species,i-1), dim=1)
     505            0 :             if (qi_max == qim_max) then  ! merge with smaller neighbor
     506            0 :                if (i+1 == nz) then
     507            0 :                   drL = s% r(nz) - s% R_center
     508              :                else
     509            0 :                   drL = s% r(i) - s% r(i+1)
     510              :                end if
     511            0 :                drR = s% r(i-1) - s% r(i)
     512            0 :                if (drR < drL) i = i-1
     513              :             ! else i-1 has different most abundant species,
     514              :                ! so don't consider merging with it
     515              :             end if
     516              :          end if
     517              : 
     518            0 :          merge_center = (i == nz)
     519            0 :          if (merge_center) i = i-1
     520            0 :          ip = i+1
     521            0 :          if (s% split_merge_amr_avoid_repeated_remesh .and. &
     522              :                (s% amr_split_merge_has_undergone_remesh(i) .or. &
     523              :                   s% amr_split_merge_has_undergone_remesh(ip))) then
     524            0 :             s% amr_split_merge_has_undergone_remesh(i) = .true.
     525            0 :             s% amr_split_merge_has_undergone_remesh(ip) = .true.
     526              : 
     527            0 :             return
     528              :          end if
     529              : 
     530              :          ! merge contents of zone ip into zone i; remove zone ip
     531              :          ! get energies for i and ip before merge
     532            0 :          call get_cell_energies(s, i, Esum_i, KE_i, PE_i, IE_i, Etrb_i)
     533            0 :          call get_cell_energies(s, ip, Esum_ip, KE_ip, PE_ip, IE_ip, Etrb_ip)
     534              : 
     535            0 :          if (s% rotation_flag) then
     536              :             ! WARNING! this is designed to conserve angular momentum, but not to explicitly conserve energy
     537            0 :             j_rot_new = 0d0
     538            0 :             j_rot_p1_new = 0d0
     539            0 :             if (i==1) then
     540            0 :                dmbar_old = 0.5d0*s% dm(i)
     541              :             else
     542            0 :                dmbar_old = 0.5d0*(s% dm(i)+s% dm(i-1))
     543              :             end if
     544            0 :             if (ip /= nz) then
     545            0 :                dmbar_p1_old = 0.5d0*(s% dm(ip)+s% dm(ip-1))
     546            0 :                if (ip+1 /= nz) then
     547            0 :                   dmbar_p2_old = 0.5d0*(s% dm(ip+1)+s% dm(ip))
     548              :                else
     549            0 :                   dmbar_p2_old = s% dm(nz) + 0.5d0*s% dm(nz-1)
     550              :                end if
     551              :                ! before merge we have (for i/=nz)
     552              :                ! dmbar_old + dmbar_p1_old = 0.5*(m(i-1)+m(i))-0.5*(m(i+1)+m(i+2))
     553              :                ! after merge we have the merged dm_bar_new
     554              :                ! dmbar_new = 0.5*(m(i-1)+m(i)) - 0.5*(m(i)+m(i+2)) = 0.5*(m(i-1)-m(i+2))
     555              :                ! where m is the old mass coordinate. From this we have dmbar_new < dmbar_old,
     556              :                ! dmbar_old + dmbar_p1_old = dmbar_new + 0.5*(m(i) - m(i+1)) = dmbar_new + 0.5*dm(i)
     557              :                ! this last expression also holds if i=nz
     558            0 :                dmbar_new = dmbar_old + dmbar_p1_old - 0.5d0*s% dm(i)
     559              :                ! this difference in mass goes to the dm_bar below
     560            0 :                dmbar_p1_new = dmbar_p2_old + 0.5d0*s% dm(i)
     561              :                ! for the merged cell we take the specific angular momentum of both merged cells
     562            0 :                J_old = dmbar_old*s% j_rot(i) + dmbar_p1_old*s% j_rot(ip)
     563            0 :                j_rot_new = J_old/(dmbar_old + dmbar_p1_old)
     564              :                ! and the j_rot of the cell downwards is adjusted to preserve angular momentum
     565            0 :                J_old = J_old + dmbar_p2_old*s% j_rot(ip+1)
     566            0 :                j_rot_p1_new = (J_old - j_rot_new*dmbar_new)/dmbar_p1_new
     567              :                ! which satisfies:
     568              :                ! J_old = j_rot_p1_new*dmbar_p1_new + j_rot_new*dmbar_new
     569              :             else
     570            0 :                dmbar_p1_old = s% dm(nz) + 0.5d0*s% dm(nz-1)
     571              :                ! simple case, dmbar_new is equal to dmbar_old plus dmbar_p1_old
     572              :                ! no need to adjust j_rot of another cell downwards
     573            0 :                dmbar_new = dmbar_old + dmbar_p1_old
     574            0 :                j_rot_new = (dmbar_old*s% j_rot(i) + dmbar_p1_old*s% j_rot(ip))/dmbar_new
     575            0 :                j_rot_p1_new = 0d0
     576              :                !write(*,*) "check center", i, ip, j_rot_new, j_rot_p1_new
     577              :             end if
     578              :          end if
     579              : 
     580            0 :          dm_i = s% dm(i)
     581            0 :          dm_ip = s% dm(ip)
     582            0 :          dm = dm_i + dm_ip
     583            0 :          s% dm(i) = dm
     584            0 :          s% dq(i) = dm/s% xmstar
     585              : 
     586            0 :          if (s% RTI_flag) &
     587            0 :             s% alpha_RTI(i) = (dm_i*s% alpha_RTI(i) + dm_ip*s% alpha_RTI(ip))/dm
     588            0 :          do q=1,species
     589            0 :             s% xa(q,i) = (dm_i*s% xa(q,i) + dm_ip*s% xa(q,ip))/dm
     590              :          end do
     591              : 
     592            0 :          KE = KE_i + KE_ip
     593            0 :          if (s% u_flag) then
     594            0 :             v = sqrt(KE/(0.5d0*dm))
     595            0 :             if (s% u(i) < 0d0) v = -v
     596            0 :             s% u(i) = v
     597              :          else if (s% v_flag) then
     598              :             ! there's no good solution for this.
     599              :             ! so just leave s% v(i) unchanged.
     600              :          end if
     601              : 
     602            0 :          cell_ie = IE_i + IE_ip
     603            0 :          s% energy(i) = cell_ie/dm
     604              : 
     605            0 :          if (s% RSP2_flag) then
     606            0 :             cell_etrb = Etrb_i + Etrb_ip
     607            0 :             s% w(i) = sqrt(cell_etrb/dm)
     608              :          end if
     609              : 
     610            0 :          if (s% rotation_flag) then
     611            0 :             s% j_rot(i) = j_rot_new
     612            0 :             if (ip/=nz) then
     613            0 :                s% j_rot(ip+1) = j_rot_p1_new
     614              :             end if
     615              :          end if
     616              : 
     617              :          ! shift ip+1...nz down by 1 to ip...nz-1
     618            0 :          do i0 = ip+1, nz
     619            0 :             im = i0-1
     620              :             !write(*,3) 'shift to im from i0', im, i0
     621            0 :             do q=1,species
     622            0 :                s% xa(q,im) = s% xa(q,i0)
     623              :             end do
     624            0 :             do q=1,s% nvar_hydro
     625            0 :                s% xh(q,im) = s% xh(q,i0)
     626              :             end do
     627            0 :             s% r(im) = s% r(i0)
     628            0 :             s% rmid(im) = s% rmid(i0)
     629            0 :             s% dm(im) = s% dm(i0)
     630            0 :             s% m(im) = s% m(i0)
     631            0 :             s% dq(im) = s% dq(i0)
     632            0 :             s% q(im) = s% q(i0)
     633            0 :             if (s% u_flag) then
     634            0 :                s% u(im) = s% u(i0)
     635            0 :             else if (s% v_flag) then
     636            0 :                s% v(im) = s% v(i0)
     637              :             end if
     638            0 :             if (s% RSP2_flag) then
     639            0 :                s% w(im) = s% w(i0)
     640            0 :                s% Hp_face(im) = s% Hp_face(i0)
     641              :             end if
     642            0 :             s% energy(im) = s% energy(i0)
     643            0 :             s% dPdr_dRhodr_info(im) = s% dPdr_dRhodr_info(i0)
     644            0 :             s% cgrav(im) = s% cgrav(i0)
     645            0 :             s% alpha_mlt(im) = s% alpha_mlt(i0)
     646            0 :             s% lnT(im) = s% lnT(i0)
     647            0 :             s% D_mix(im) = s% D_mix(i0)
     648            0 :             s% mlt_vc(im) = s% mlt_vc(i0)
     649            0 :             s% csound(im) = s% csound(i0)
     650            0 :             s% tau(im) = s% tau(i0)
     651            0 :             s% opacity(im) = s% opacity(i0)
     652            0 :             s% amr_split_merge_has_undergone_remesh(im) = s% amr_split_merge_has_undergone_remesh(i0)
     653            0 :             if (s% RTI_flag) s% alpha_RTI(im) = s% alpha_RTI(i0)
     654            0 :             if (s% rotation_flag) s% j_rot(im) = s% j_rot(i0)
     655              :          end do
     656            0 :          s% amr_split_merge_has_undergone_remesh(i) = .true.
     657              : 
     658            0 :          nz = nz - 1
     659            0 :          s% nz = nz
     660              : 
     661            0 :          if (s% u_flag) then
     662            0 :             s% xh(s% i_u,i) = s% u(i)
     663            0 :          else if (s% v_flag) then
     664            0 :             s% xh(s% i_v,i) = s% v(i)
     665              :          end if
     666              : 
     667            0 :          if (s% RTI_flag) s% xh(s% i_alpha_RTI,i) = s% alpha_RTI(i)
     668              : 
     669            0 :          if (s% RSP2_flag) then
     670            0 :             s% xh(s% i_w,i) = s% w(i)
     671            0 :             s% xh(s% i_Hp,i) = s% Hp_face(i)
     672              :          end if
     673              : 
     674              :          ! do this after move cells since need new r(ip) to calc new rho(i).
     675            0 :          call update_xh_eos_and_kap(s,i,species,new_xa,ierr)
     676            0 :          if (ierr /= 0) return  ! call mesa_error(__FILE__,__LINE__,'update_xh_eos_and_kap failed in do_merge')
     677              : 
     678            0 :          s% rmid_start(i) = -1
     679            0 :          call set_rmid(s, i, i, ierr)
     680            0 :          if (ierr /= 0) return  ! call mesa_error(__FILE__,__LINE__,'update_xh_eos_and_kap failed in do_merge')
     681              : 
     682            0 :          star_PE1 = get_star_PE(s)
     683            0 :          call revise_star_radius(s, star_PE0, star_PE1)
     684              : 
     685            0 :       end subroutine do_merge
     686              : 
     687              : 
     688            0 :       subroutine revise_star_radius(s, star_PE0, star_PE1)
     689            0 :          use star_utils, only: store_r_in_xh, get_lnR_from_xh
     690              :          type (star_info), pointer :: s
     691              :          real(dp), intent(in) :: star_PE0, star_PE1
     692              :          integer :: k
     693              :          real(dp) :: frac
     694              :          include 'formats'
     695            0 :          if (star_PE1 == 0d0 .or. star_PE0 == star_PE1) return
     696            0 :          frac = star_PE1/star_PE0
     697            0 :          if (s% model_number == -6918) write(*,1) 'frac', frac
     698            0 :          if (s% model_number == -6918) write(*,1) 'star_PE0', star_PE0
     699            0 :          if (s% model_number == -6918) write(*,1) 'star_PE1', star_PE1
     700            0 :          do k=1,s% nz
     701            0 :             s% r(k) = s% r(k)*frac
     702            0 :             if (s% model_number == -6918) write(*,2) 's% r(k)', k, s% r(k)
     703            0 :             call store_r_in_xh(s, k, s% r(k))
     704            0 :             s% lnR(k) = get_lnR_from_xh(s,k)
     705              :          end do
     706            0 :          s% r_center = frac*s% r_center
     707            0 :       end subroutine revise_star_radius
     708              : 
     709              : 
     710            0 :       real(dp) function get_star_PE(s) result(totPE)
     711              :          type (star_info), pointer :: s
     712              :          integer :: k
     713            0 :          real(dp) :: PE, rL, rC, dm, mC
     714            0 :          totPE = 0d0
     715            0 :          do k=1,s% nz
     716            0 :             if (k == s% nz) then
     717            0 :                rL = s% R_center
     718              :             else
     719            0 :                rL = s% r(k+1)
     720              :             end if
     721            0 :             rC = 0.5d0*(rL + s% r(k))
     722            0 :             dm = s% dm(k)
     723            0 :             mC = s% m(k) - 0.5d0*dm
     724            0 :             PE = -s% cgrav(k)*mC*dm/rC
     725            0 :             totPE = totPE + PE
     726              :          end do
     727            0 :       end function get_star_PE
     728              : 
     729              : 
     730            0 :       subroutine get_cell_energies(s, k, Etot, KE, PE, IE, Etrb)
     731              :          type (star_info), pointer :: s
     732              :          integer, intent(in) :: k
     733              :          real(dp), intent(out) :: Etot, KE, PE, IE, Etrb
     734            0 :          real(dp) :: dm, mC, v0, v1, rL, rC
     735              :          include 'formats'
     736            0 :          dm = s% dm(k)
     737            0 :          if (s% u_flag) then
     738            0 :             KE = 0.5d0*dm*s% u(k)**2
     739            0 :          else if (s% v_flag) then
     740            0 :             v0 = s% v(k)
     741            0 :             if (k < s% nz) then
     742            0 :                v1 = s% v(k+1)
     743              :             else
     744            0 :                v1 = s% v_center
     745              :             end if
     746            0 :             KE = 0.25d0*dm*(v0**2 + v1**2)
     747              :          else
     748            0 :             KE = 0d0
     749              :          end if
     750            0 :          IE = s% energy(k)*dm
     751            0 :          if (s% RSP2_flag) then
     752            0 :             Etrb = pow2(s% w(k))*dm
     753              :          else
     754            0 :             Etrb = 0d0
     755              :          end if
     756            0 :          if (s% cgrav(k) == 0) then
     757            0 :             PE = 0
     758              :          else
     759            0 :             if (k == s% nz) then
     760            0 :                rL = s% R_center
     761              :             else
     762            0 :                rL = s% r(k+1)
     763              :             end if
     764            0 :             rC = 0.5d0*(rL + s% r(k))
     765            0 :             mC = s% m(k) - 0.5d0*dm
     766            0 :             PE = -s% cgrav(k)*mC*dm/rC
     767              :          end if
     768            0 :          Etot = IE + KE + PE
     769              :          if (is_bad(Etot + IE + KE + PE) .or. &
     770            0 :              IE <= 0 .or. KE < 0) then
     771            0 :             write(*,2) 'nz', s% nz
     772            0 :             write(*,2) 'Etot', k, Etot
     773            0 :             write(*,2) 'IE', k, IE
     774            0 :             write(*,2) 'KE', k, KE
     775            0 :             write(*,2) 'PE', k, PE
     776            0 :             call mesa_error(__FILE__,__LINE__,'get_cell_energies')
     777              :          end if
     778            0 :       end subroutine get_cell_energies
     779              : 
     780              : 
     781            0 :       subroutine split1_non_negative( &
     782              :             val, grad, dr, dV, dVR, dVL, new_valL, new_valR)
     783              :          real(dp), intent(in) :: val, grad, dr, dV, dVR, dVL
     784              :          real(dp), intent(out) :: new_valL, new_valR
     785            0 :          real(dp) :: xL, xR, xML, xMR, xM, f
     786              :          include 'formats'
     787            0 :          new_valR = val
     788            0 :          new_valL = val
     789            0 :          if (val < 1d-99 .or. grad == 0d0) return
     790            0 :          xL = max(0d0, min(1d0, val - grad*dr/4))
     791            0 :          xR = max(0d0, min(1d0, val + grad*dr/4))
     792            0 :          xML = xL*dVL
     793            0 :          xMR = xR*dVR
     794            0 :          xM = val*dV
     795            0 :          if (xM < 1d-99 .or. xML + xMR < 1d-99) then
     796              :             new_valR = val
     797              :             new_valL = val
     798              :          else
     799            0 :             f = xM/(xML + xMR)
     800            0 :             new_valR = f*xR
     801            0 :             new_valL = f*xL
     802              :          end if
     803              :       end subroutine split1_non_negative
     804              : 
     805              : 
     806            0 :       subroutine do_split(s, i_split, species, tau_center, grad_xa, new_xa, ierr)
     807              :          use alloc, only: reallocate_star_info_arrays
     808              :          use star_utils, only: set_rmid, store_r_in_xh
     809              :          type (star_info), pointer :: s
     810              :          integer, intent(in) :: i_split, species
     811              :          real(dp) :: tau_center, grad_xa(species), new_xa(species)
     812              :          integer, intent(out) :: ierr
     813              :          integer :: i, ip, j, jp, q, nz, nz_old, &
     814              :             iR, iC, iL
     815              :          real(dp) :: &
     816              :             cell_Esum_old, cell_KE_old, cell_PE_old, cell_IE_old, cell_Etrb_old, &
     817            0 :             rho_RR, rho_iR, rR, rL, dr, dr_old, rC, dV, dVR, dVL, dM, dML, dMR, rho, &
     818            0 :             v, v2, energy, v2_R, energy_R, rho_R, v2_C, energy_C, rho_C, v2_L, energy_L, rho_L, &
     819            0 :             dLeft, dRght, dCntr, grad_rho, grad_energy, grad_v2, &
     820            0 :             sumx, sumxp, new_xaL, new_xaR, star_PE0, star_PE1, &
     821            0 :             grad_alpha, f, new_alphaL, new_alphaR, v_R, v_C, v_L, min_dm, &
     822            0 :             mlt_vcL, mlt_vcR, tauL, tauR, etrb, etrb_L, etrb_C, etrb_R, grad_etrb, &
     823            0 :             j_rot_new, dmbar_old, dmbar_p1_old, dmbar_new, dmbar_p1_new, dmbar_p2_new, J_old
     824              :          logical :: done, use_new_grad_rho
     825              :          include 'formats'
     826              : 
     827            0 :          ierr = 0
     828            0 :          star_PE0 = get_star_PE(s)
     829            0 :          s% need_to_setvars = .true.
     830            0 :          nz = s% nz
     831            0 :          s% num_hydro_splits = s% num_hydro_splits + 1
     832            0 :          done = .false.
     833            0 :          nz_old = nz
     834              : 
     835            0 :          i = i_split
     836            0 :          ip = i+1
     837              : 
     838              :          call get_cell_energies( &
     839            0 :             s, i, cell_Esum_old, cell_KE_old, cell_PE_old, cell_IE_old, cell_Etrb_old)
     840              : 
     841            0 :          if (s% rotation_flag .and. i<nz) then
     842              :             ! WARNING! this is designed to conserve angular momentum, but not to explicitly conserve energy
     843            0 :             if (i==1) then
     844            0 :                dmbar_old = 0.5d0*s% dm(i)
     845              :             else
     846            0 :                dmbar_old = 0.5d0*(s% dm(i)+s% dm(i-1))
     847              :             end if
     848            0 :             if (ip /= nz) then
     849            0 :                dmbar_p1_old = 0.5d0*(s% dm(ip)+s% dm(ip-1))
     850              :             else
     851            0 :                dmbar_p1_old = s% dm(ip)+0.5d0*s% dm(ip-1)
     852              :             end if
     853              : 
     854              :             ! We need to conserve the angular momentum in these two cells
     855            0 :             J_old = dmbar_old*s% j_rot(i) + dmbar_p1_old*s% j_rot(ip)
     856              :          end if
     857              : 
     858            0 :          rR = s% r(i)
     859            0 :          mlt_vcR = s% mlt_vc(i)
     860            0 :          if (i == nz) then
     861            0 :             rL = s% R_center
     862            0 :             mlt_vcL = 0d0
     863              :             tauL = tau_center
     864              :          else
     865            0 :             rL = s% r(ip)
     866            0 :             mlt_vcL = s% mlt_vc(ip)
     867              :             tauL = s% tau(ip)
     868              :          end if
     869              : 
     870            0 :          tauR = s% tau(i)
     871            0 :          if (i == nz) then
     872            0 :             tauL = tau_center
     873              :          else
     874            0 :             tauL = s% tau(ip)
     875              :          end if
     876            0 :          if (is_bad(tauL+tauR)) then
     877            0 :             !$omp critical (adjust_mesh_split_merge_crit1)
     878            0 :             write(*,2) 'tauL', ip, tauL
     879            0 :             write(*,2) 'tauR', i, tauR
     880            0 :             write(*,2) 'nz', nz
     881            0 :             call mesa_error(__FILE__,__LINE__,'do_split')
     882              :             !$omp end critical (adjust_mesh_split_merge_crit1)
     883              :          end if
     884              : 
     885            0 :          dr = rR - rL
     886            0 :          dr_old = dr
     887            0 :          rC = 0.5d0*(rR + rL)  ! split at center by radius
     888              : 
     889            0 :          dV = four_thirds_pi*(rR*rR*rR - rL*rL*rL)
     890            0 :          dVR = four_thirds_pi*(rR*rR*rR - rC*rC*rC)
     891            0 :          dVL = dV - dVR
     892              : 
     893            0 :          dm = s% dm(i)
     894            0 :          rho = dm/dV
     895              : 
     896            0 :          if (s% u_flag) then
     897            0 :             v = s% u(i)
     898            0 :             v2 = v*v
     899              :          else  ! not used
     900              :             v = 0
     901              :             v2 = 0
     902              :          end if
     903              : 
     904            0 :          energy = s% energy(i)
     905            0 :          if (s% RSP2_flag) etrb = pow2(s% w(i))
     906              : 
     907              :          ! use iR, iC, and iL for getting values to determine slopes
     908            0 :          if (i > 1 .and. i < nz_old) then
     909            0 :             iR = i-1
     910            0 :             iC = i
     911            0 :             iL = i+1
     912            0 :          else if (i == 1) then
     913            0 :             iR = 1
     914            0 :             iC = 2
     915            0 :             iL = 3
     916              :          else  ! i == nz_old
     917            0 :             iR = nz_old-2
     918            0 :             iC = nz_old-1
     919            0 :             iL = nz_old
     920              :          end if
     921              : 
     922            0 :          energy_R = s% energy(iR)
     923            0 :          rho_R = s% dm(iR)/get_dV(s,iR)
     924              : 
     925            0 :          energy_C = s% energy(iC)
     926            0 :          rho_C = s% dm(iC)/get_dV(s,iC)
     927              : 
     928            0 :          energy_L = s% energy(iL)
     929            0 :          rho_L = s% dm(iL)/get_dV(s,iL)
     930              : 
     931              :          ! get gradients before move cell contents
     932              : 
     933            0 :          if (iL == nz_old) then
     934            0 :             dLeft = 0.5d0*(s% r(iC) - s% R_center)
     935              :          else
     936            0 :             dLeft = 0.5d0*(s% r(iC) - s% r(iL+1))
     937              :          end if
     938            0 :          dRght = 0.5d0*(s% r(iR) - s% r(iL))
     939            0 :          dCntr = dLeft + dRght
     940              : 
     941            0 :          if (s% equal_split_density_amr) then  ! same density in both parts
     942            0 :             rho_RR = 0
     943              :             grad_rho = 0d0
     944              :             use_new_grad_rho = .false.
     945              :          else if (.false.) then
     946              :             rho_RR = s% dm(iR-1)/get_dV(s,iR-1)
     947              :             grad_rho = 2*(rho_RR - rho_R)/(s% r(iR-1) - s% r(iR+1))
     948              :             use_new_grad_rho = .true.
     949              :          else
     950            0 :             rho_RR = 0
     951            0 :             grad_rho = get1_grad(rho_L, rho_C, rho_R, dLeft, dCntr, dRght)
     952            0 :             use_new_grad_rho = .false.
     953              :          end if
     954              : 
     955            0 :          grad_energy = get1_grad(energy_L, energy_C, energy_R, dLeft, dCntr, dRght)
     956              : 
     957            0 :          if (s% RTI_flag) grad_alpha = get1_grad( &
     958            0 :             s% alpha_RTI(iL), s% alpha_RTI(iC), s% alpha_RTI(iR), dLeft, dCntr, dRght)
     959              : 
     960            0 :          if (s% RSP2_flag) then
     961            0 :             etrb_R = pow2(s% w(iR))
     962            0 :             etrb_C = pow2(s% w(iC))
     963            0 :             etrb_L = pow2(s% w(iL))
     964            0 :             grad_etrb = get1_grad(etrb_L, etrb_C, etrb_R, dLeft, dCntr, dRght)
     965              :          end if
     966              : 
     967            0 :          if (s% u_flag) then
     968            0 :             v_R = s% u(iR)
     969            0 :             v2_R = v_R*v_R
     970            0 :             v_C = s% u(iC)
     971            0 :             v2_C = v_C*v_C
     972            0 :             v_L = s% u(iL)
     973            0 :             v2_L = v_L*v_L
     974            0 :             if ((v_L - v_C)*(v_C - v_R) <= 0) then  ! not strictly monotonic velocities
     975              :                grad_v2 = 0d0
     976              :             else
     977            0 :                grad_v2 = get1_grad(v2_L, v2_C, v2_R, dLeft, dCntr, dRght)
     978              :             end if
     979            0 :          else if (s% v_flag) then
     980            0 :             if (iL == s% nz) then
     981            0 :                v_L = s% v_center
     982              :             else
     983            0 :                v_L = s% v(ip)
     984              :             end if
     985            0 :             v2_L = v_L*v_L
     986            0 :             v_R = s% v(i)
     987            0 :             v2_R = v_R*v_R
     988              :          end if
     989              : 
     990            0 :          do q = 1, species
     991              :             grad_xa(q) = get1_grad( &
     992            0 :                s% xa(q,iL), s% xa(q,iC), s% xa(q,iR), dLeft, dCntr, dRght)
     993              :          end do
     994              : 
     995            0 :          nz = nz + 1
     996            0 :          s% nz = nz
     997            0 :          call reallocate_star_info_arrays(s, ierr)
     998            0 :          if (ierr /= 0) then
     999            0 :             write(*,2) 'reallocate_star_info_arrays ierr', ierr
    1000            0 :             call mesa_error(__FILE__,__LINE__,'split failed')
    1001              :          end if
    1002              : 
    1003            0 :          if (i_split < nz_old) then  ! move i_split..nz-1 to i_split+1..nz
    1004            0 :             do j=nz-1,i_split,-1
    1005            0 :                jp = j+1
    1006            0 :                do q=1,species
    1007            0 :                   s% xa(q,jp) = s% xa(q,j)
    1008              :                end do
    1009            0 :                do q=1,s% nvar_hydro
    1010            0 :                   s% xh(q,jp) = s% xh(q,j)
    1011              :                end do
    1012            0 :                s% r(jp) = s% r(j)
    1013            0 :                s% rmid(jp) = s% rmid(j)
    1014            0 :                s% dm(jp) = s% dm(j)
    1015            0 :                s% m(jp) = s% m(j)
    1016            0 :                s% dq(jp) = s% dq(j)
    1017            0 :                s% q(jp) = s% q(j)
    1018            0 :                if (s% u_flag) then
    1019            0 :                   s% u(jp) = s% u(j)
    1020            0 :                else if (s% v_flag) then
    1021            0 :                   s% v(jp) = s% v(j)
    1022              :                end if
    1023            0 :                s% energy(jp) = s% energy(j)
    1024            0 :                s% dPdr_dRhodr_info(jp) = s% dPdr_dRhodr_info(j)
    1025            0 :                s% cgrav(jp) = s% cgrav(j)
    1026            0 :                s% alpha_mlt(jp) = s% alpha_mlt(j)
    1027            0 :                s% lnT(jp) = s% lnT(j)
    1028            0 :                s% D_mix(jp) = s% D_mix(j)
    1029            0 :                s% mlt_vc(jp) = s% mlt_vc(j)
    1030            0 :                s% csound(jp) = s% csound(j)
    1031            0 :                s% tau(jp) = s% tau(j)
    1032            0 :                s% opacity(jp) = s% opacity(j)
    1033            0 :                s% amr_split_merge_has_undergone_remesh(jp) = s% amr_split_merge_has_undergone_remesh(j)
    1034            0 :                if (s% RTI_flag) s% alpha_RTI(jp) = s% alpha_RTI(j)
    1035            0 :                if (s% rotation_flag) s% j_rot(jp) = s% j_rot(j)
    1036              :             end do
    1037              :          end if
    1038            0 :          s% amr_split_merge_has_undergone_remesh(i) = .true.
    1039            0 :          s% amr_split_merge_has_undergone_remesh(ip) = .true.
    1040              : 
    1041            0 :          dM = rho*dV
    1042              :          if (.not. use_new_grad_rho) then  ! do it the old way
    1043              : 
    1044            0 :             rho_L = rho - grad_rho*dr/4
    1045            0 :             rho_R = rho + grad_rho*dr/4
    1046              :             if (grad_rho == 0d0 .or. &
    1047            0 :                   rho_L <= 0d0 .or. &
    1048              :                   rho_R <= 0d0) then
    1049            0 :                rho_R = rho
    1050            0 :                rho_L = rho
    1051            0 :                dML = rho_L*dVL
    1052            0 :                dMR = dM - dML  ! should = rhoR*dVR
    1053              :             else
    1054            0 :                dML = rho_L*dVL
    1055            0 :                dMR = rho_R*dVR
    1056            0 :                f = dM/(dML + dMR)
    1057            0 :                rho_L = f*rho_L
    1058            0 :                rho_R = f*rho_R
    1059            0 :                dML = rho_L*dVL
    1060            0 :                dMR = rho_R*dVR
    1061            0 :                if (abs(dML + dMR - dM) > 1d-14*dM) then
    1062            0 :                   write(*,2) '(dML + dMR - dM)/dM', i, (dML + dMR - dM)/dM
    1063            0 :                   call mesa_error(__FILE__,__LINE__,'split')
    1064              :                end if
    1065            0 :                dMR = dM - dML
    1066              :             end if
    1067              : 
    1068              :          else
    1069              : 
    1070              :             ! at this point, rho_R is the density of the cell iR
    1071              :             ! we are about to redefine it as the density of the right 1/2 of the split
    1072              :             ! similarly for rho_L
    1073              :             rho_iR = rho_R
    1074              :             dR = -(dRght/4 + (s% r(iR) - s% r(iC))/2)
    1075              :             rho_R = rho_iR + grad_rho*dR
    1076              :             dMR = rho_R*dVR
    1077              :             dML = dM - dMR
    1078              :             rho_L = dML/dVL
    1079              :             if (rho_R <= 1d-16 .or. rho_L <= 1d-16) then
    1080              :    !$omp critical (adjust_mesh_split_merge_crit2)
    1081              :                write(*,'(A)')
    1082              :                write(*,2) 'nz', nz
    1083              :                write(*,2) 'rho_RR', iR-1, rho_RR
    1084              :                write(*,2) 'rho_iR', iR, rho_iR
    1085              :                write(*,2) 'rho', iC, rho
    1086              :                write(*,2) 's% r(iR-1)', iR-1, s% r(iR-1)
    1087              :                write(*,2) 's% r(iR)', iR, s% r(iR)
    1088              :                write(*,2) 's% r(iR+1)', iR+1, s% r(iR+1)
    1089              :                write(*,2) 'rho_RR', iR-1, rho_RR
    1090              :                write(*,2) 'rho_iR', iR, rho_iR
    1091              :                write(*,2) 'rho_RR - rho_iR', iR, rho_RR - rho_iR
    1092              :                write(*,2) 'dr for right', iR, (s% r(iR-1) - s% r(iR+1))/2
    1093              :                write(*,2) 'grad_rho', iR, grad_rho
    1094              :                write(*,'(A)')
    1095              :                write(*,2) 's% r(iL)', iL, s% r(iL)
    1096              :                write(*,2) 'dR', iC, dR
    1097              :                write(*,2) 'dRho', iC, grad_rho*dR
    1098              :                write(*,2) 'rho_R', iC, rho_R
    1099              :                write(*,2) 'rho_L', iC, rho_L
    1100              :                write(*,'(A)')
    1101              :                call mesa_error(__FILE__,__LINE__,'failed in do_split extrapolation of density from above')
    1102              :    !$omp end critical  (adjust_mesh_split_merge_crit2)
    1103              :             end if
    1104              : 
    1105              :          end if
    1106              : 
    1107            0 :          min_dm = s% split_merge_amr_dq_min*s% xmstar
    1108            0 :          if (dML < min_dm .or. dMR < min_dm) then
    1109            0 :             rho_R = rho
    1110            0 :             rho_L = rho
    1111            0 :             dM = rho*dV
    1112            0 :             dML = rho_L*dVL
    1113            0 :             dMR = dM - dML  ! should = rhoR*dVR
    1114              :          end if
    1115              : 
    1116            0 :          energy_R = energy + grad_energy*dr/4
    1117            0 :          energy_L = (dm*energy - dmR*energy_R)/dmL
    1118            0 :          if (energy_R < 0d0 .or. energy_L < 0d0) then
    1119            0 :             energy_R = energy
    1120            0 :             energy_L = energy
    1121              :          end if
    1122              : 
    1123            0 :          s% energy(i) = energy_R
    1124            0 :          s% energy(ip) = energy_L
    1125              : 
    1126            0 :          if (s% RSP2_flag) then
    1127            0 :             etrb_R = etrb + grad_etrb*dr/4
    1128            0 :             etrb_L = (dm*etrb - dmR*etrb_R)/dmL
    1129            0 :             if (etrb_R < 0d0 .or. etrb_L < 0d0) then
    1130            0 :                etrb_R = etrb
    1131            0 :                etrb_L = etrb
    1132              :             end if
    1133            0 :             s% w(i) = sqrt(max(0d0,etrb_R))
    1134            0 :             s% w(ip) = sqrt(max(0d0,etrb_L))
    1135              :          end if
    1136              : 
    1137            0 :          if (s% u_flag) then
    1138            0 :             v2_R = v2 + grad_v2*dr/4
    1139            0 :             v2_L = (dm*v2 - dmR*v2_R)/dmL
    1140            0 :             if (v2_R < 0d0 .or. v2_L < 0d0) then
    1141            0 :                v2_R = v2
    1142            0 :                v2_L = v2
    1143              :             end if
    1144            0 :             s% u(i) = sqrt(v2_R)
    1145            0 :             s% u(ip) = sqrt(v2_L)
    1146            0 :             if (v < 0d0) then
    1147            0 :                s% u(i) = -s% u(i)
    1148            0 :                s% u(ip) = -s% u(ip)
    1149              :             end if
    1150            0 :          else if (s% v_flag) then  ! just make a rough approximation.
    1151            0 :             s% v(ip) = sqrt(0.5d0*(v2_L + v2_R))
    1152              :          end if
    1153              : 
    1154            0 :          if (s% RTI_flag) then  ! set new alpha
    1155            0 :             if (i == 1) then
    1156            0 :                s% alpha_RTI(ip) = s% alpha_RTI(i)
    1157              :             else
    1158              :                call split1_non_negative( &
    1159              :                   s% alpha_RTI(i), grad_alpha, &
    1160            0 :                   dr, dV, dVR, dVL, new_alphaL, new_alphaR)
    1161            0 :                s% alpha_RTI(i) = new_alphaR
    1162            0 :                s% alpha_RTI(ip) = new_alphaL
    1163              :             end if
    1164            0 :             s% dPdr_dRhodr_info(ip) = s% dPdr_dRhodr_info(i)
    1165              :          end if
    1166              : 
    1167            0 :          if (i == 1) then
    1168            0 :             s% mlt_vc(ip) = s% mlt_vc(i)
    1169              :          else
    1170            0 :             s% mlt_vc(ip) = (mlt_vcL*dML + mlt_vcR*dMR)/dM
    1171              :          end if
    1172              : 
    1173            0 :          s% tau(ip) = tauR + (tauL - tauR)*dMR/dM
    1174            0 :          if (is_bad(s% tau(ip))) then
    1175            0 :             write(*,2) 'tau', ip, s% tau(ip), tauL, tauR, dMR/dM
    1176            0 :             call mesa_error(__FILE__,__LINE__,'split')
    1177              :          end if
    1178              : 
    1179            0 :          if (i == 1) then
    1180            0 :             do q=1,species
    1181            0 :                s% xa(q,ip) = s% xa(q,i)
    1182              :             end do
    1183              :          else  ! split mass fractions
    1184              :             ! check that sum of grads for mass fractions is 0
    1185            0 :             sumx = sum(grad_xa)
    1186            0 :             if (sumx > 0) then  ! reduce largest grad
    1187            0 :                j = maxloc(grad_xa, dim=1)
    1188              :             else  ! increase smallest grad
    1189            0 :                j = minloc(grad_xa, dim=1)
    1190              :             end if
    1191            0 :             grad_xa(j) = 0
    1192            0 :             grad_xa(j) = -sum(grad_xa)
    1193              :             ! set new mass fractions
    1194            0 :             do q = 1, species
    1195              :                call split1_non_negative( &
    1196              :                   s% xa(q,i), grad_xa(q), &
    1197            0 :                   dr, dV, dVR, dVL, new_xaL, new_xaR)
    1198            0 :                s% xa(q,i) = new_xaR
    1199            0 :                s% xa(q,ip) = new_xaL
    1200              :             end do
    1201              :             !check mass fractions >= 0 and <= 1 and sum to 1.0
    1202            0 :             do q = 1, species
    1203            0 :                s% xa(q,i) = min(1d0, max(0d0, s% xa(q,i)))
    1204            0 :                s% xa(q,ip) = min(1d0, max(0d0, s% xa(q,ip)))
    1205              :             end do
    1206            0 :             sumx = sum(s% xa(1:species,i))
    1207            0 :             sumxp = sum(s% xa(1:species,ip))
    1208            0 :             do q = 1, species
    1209            0 :                s% xa(q,i) = s% xa(q,i)/sumx
    1210            0 :                s% xa(q,ip) = s% xa(q,ip)/sumxp
    1211              :             end do
    1212              :          end if
    1213              : 
    1214            0 :          if (s% u_flag) s% u_face_ad(ip)%val = 0.5d0*(s% u(i) + s% u(ip))
    1215              :             ! just for setting u_face_start so don't need partials
    1216              : 
    1217              :          ! r, q, m, u_face unchanged for face i
    1218            0 :          dVR = dV - dVL
    1219            0 :          dmR = s% dm(i) - dmL
    1220            0 :          s% dm(i) = dmR
    1221            0 :          s% dq(i) = s% dm(i)/s% xmstar
    1222              : 
    1223            0 :          s% r(ip) = rC
    1224            0 :          s% m(ip) = s% m(i) - s% dm(i)  ! <<< using new value dm(i)
    1225            0 :          s% q(ip) = s% q(i) - s% dq(i)  ! <<< using new value dq(i)
    1226            0 :          s% dm(ip) = dmL
    1227            0 :          s% dq(ip) = s% dm(ip)/s% xmstar
    1228              : 
    1229            0 :          s% cgrav(ip) = s% cgrav(i)
    1230            0 :          s% alpha_mlt(ip) = s% alpha_mlt(i)
    1231            0 :          s% lnT(ip) = s% lnT(i)
    1232            0 :          s% T(ip) = s% T(i)
    1233            0 :          s% D_mix(ip) = s% D_mix(i)
    1234            0 :          s% mlt_vc(ip) = s% mlt_vc(i)
    1235            0 :          s% csound(ip) = s% csound(i)
    1236            0 :          s% opacity(ip) = s% opacity(i)
    1237            0 :          if (s% RTI_flag) s% alpha_RTI(ip) = s% alpha_RTI(i)
    1238              : 
    1239            0 :          if (s% rotation_flag) then
    1240              :             ! WARNING! this is designed to conserve angular momentum, but not to explicitly conserve energy
    1241            0 :             j_rot_new = 0d0  ! specific angular momentum for the newly created cell
    1242            0 :             if (i==nz_old) then
    1243              :                ! simple case, dm_bar contained in cells i and i+1 after merge is conserved,
    1244              :                ! so use same j_rot
    1245            0 :                j_rot_new = s% j_rot(i)
    1246              :             else
    1247            0 :                if (i==1) then
    1248            0 :                   dmbar_new = 0.5d0*s% dm(i)
    1249              :                else
    1250            0 :                   dmbar_new = 0.5d0*(s% dm(i)+s% dm(i-1))
    1251              :                end if
    1252            0 :                if (ip /= nz) then
    1253            0 :                   dmbar_p1_new = 0.5d0*(s% dm(ip)+s% dm(ip-1))
    1254              :                else
    1255            0 :                   dmbar_p1_new = s% dm(ip)+0.5d0*s% dm(ip-1)
    1256              :                end if
    1257            0 :                if (ip+1 /= nz) then
    1258            0 :                   dmbar_p2_new = 0.5d0*(s% dm(ip+1)+s% dm(ip))
    1259              :                else
    1260            0 :                   dmbar_p2_new = s% dm(ip+1)+0.5d0*s% dm(ip)
    1261              :                end if
    1262              : 
    1263              :                ! we keep the same j_rot for cells i and ip (cells i and ip+1 after merge),
    1264              :                ! we compute the j_rot needed for the new cell to preserve angular momentum.
    1265            0 :                j_rot_new = (J_old - dmbar_new*s% j_rot(i) - dmbar_p2_new*s% j_rot(ip+1))/(dmbar_p1_new)
    1266              :                ! this satisfies:
    1267              :                ! dmbar_old*s% j_rot(i) + dmbar_p1_old*s% j_rot(ip) = dmbar_new*s% j_rot(i) + dmbar_p2_new*s% j_rot(ip) + dmbar_p1_new*j_rot_new
    1268              :             end if
    1269            0 :             s% j_rot(ip) = j_rot_new
    1270              :          end if
    1271              : 
    1272            0 :          if (s% i_lum /= 0) then
    1273            0 :             if (ip < nz_old) then
    1274              :                s% xh(s% i_lum,ip) = &
    1275            0 :                   0.5d0*(s% xh(s% i_lum,i) + s% xh(s% i_lum,ip+1))
    1276              :             else
    1277              :                s% xh(s% i_lum,ip) = &
    1278            0 :                   0.5d0*(s% xh(s% i_lum,i) + s% L_center)
    1279              :             end if
    1280              :          end if
    1281              : 
    1282            0 :          call store_r_in_xh(s, ip, s% r(ip))
    1283            0 :          if (s% u_flag) then
    1284            0 :             s% xh(s% i_u,i) = s% u(i)
    1285            0 :             s% xh(s% i_u,ip) = s% u(ip)
    1286            0 :          else if (s% v_flag) then
    1287            0 :             s% xh(s% i_v,i) = s% v(i)
    1288            0 :             s% xh(s% i_v,ip) = s% v(ip)
    1289              :          end if
    1290            0 :          if (s% RTI_flag) then
    1291            0 :             s% xh(s% i_alpha_RTI,i) = s% alpha_RTI(i)
    1292            0 :             s% xh(s% i_alpha_RTI,ip) = s% alpha_RTI(ip)
    1293              :          end if
    1294              : 
    1295            0 :          call update_xh_eos_and_kap(s,i,species,new_xa,ierr)
    1296            0 :          if (ierr /= 0) return  ! call mesa_error(__FILE__,__LINE__,'update_xh_eos_and_kap failed in do_split')
    1297              : 
    1298            0 :          call update_xh_eos_and_kap(s,ip,species,new_xa,ierr)
    1299            0 :          if (ierr /= 0) return  ! call mesa_error(__FILE__,__LINE__,'update_xh_eos_and_kap failed in do_split')
    1300              : 
    1301            0 :          s% rmid_start(i) = -1
    1302            0 :          s% rmid_start(ip) = -1
    1303            0 :          call set_rmid(s, i, ip, ierr)
    1304            0 :          if (ierr /= 0) return  ! call mesa_error(__FILE__,__LINE__,'update_xh_eos_and_kap failed in do_split')
    1305              : 
    1306            0 :          star_PE1 = get_star_PE(s)
    1307            0 :          call revise_star_radius(s, star_PE0, star_PE1)
    1308              : 
    1309            0 :       end subroutine do_split
    1310              : 
    1311              : 
    1312            0 :       subroutine update_xh_eos_and_kap(s,i,species,new_xa,ierr)
    1313            0 :          use mesh_adjust, only: set_lnT_for_energy
    1314              :          use micro, only: do_kap_for_cell
    1315              :          use eos_lib, only: eos_gamma_DE_get_PT
    1316              :          use chem_lib, only: basic_composition_info
    1317              :          use star_utils, only: store_lnT_in_xh, get_T_and_lnT_from_xh, &
    1318              :             store_rho_in_xh, get_rho_and_lnd_from_xh
    1319              :          type (star_info), pointer :: s
    1320              :          integer, intent(in) :: i, species
    1321              :          real(dp) :: new_xa(species)
    1322              :          integer, intent(out) :: ierr
    1323              :          real(dp) :: rho, logRho, new_lnT, revised_energy
    1324              :          integer :: q
    1325              :          include 'formats'
    1326            0 :          ierr = 0
    1327            0 :          rho = s% dm(i)/get_dV(s,i)
    1328            0 :          call store_rho_in_xh(s, i, rho)
    1329            0 :          call get_rho_and_lnd_from_xh(s, i, s% rho(i), s% lnd(i))
    1330            0 :          logRho = s% lnd(i)/ln10
    1331            0 :          do q=1,species
    1332            0 :             new_xa(q) = s% xa(q,i)
    1333              :          end do
    1334              :          call set_lnT_for_energy(s, i, &
    1335              :             s% net_iso(ih1), s% net_iso(ihe3), s% net_iso(ihe4), &
    1336              :             species, new_xa, rho, logRho, s% energy(i), s% lnT(i), &
    1337            0 :             new_lnT, revised_energy, ierr)
    1338            0 :          if (ierr /= 0) return
    1339            0 :          call store_lnT_in_xh(s, i, new_lnT)
    1340            0 :          call get_T_and_lnT_from_xh(s, i, s% T(i), s% lnT(i))
    1341            0 :       end subroutine update_xh_eos_and_kap
    1342              : 
    1343              : 
    1344            0 :       real(dp) function get_dV(s,k)
    1345              :          type (star_info), pointer :: s
    1346              :          integer, intent(in) :: k
    1347            0 :          if (k == s% nz) then
    1348            0 :             get_dV = four_thirds_pi*(s% r(k)*s% r(k)*s% r(k) - s% R_center*s% R_center*s% R_center)
    1349              :          else
    1350            0 :             get_dV = four_thirds_pi*(s% r(k)*s% r(k)*s% r(k) - s% r(k+1)*s% r(k+1)*s% r(k+1))
    1351              :          end if
    1352            0 :       end function get_dV
    1353              : 
    1354              : 
    1355            0 :       real(dp) function minmod(a, b, c) result(m)
    1356              :          real(dp), intent(in) :: a, b, c
    1357            0 :          m = a
    1358            0 :          if (a*b < 0d0) then
    1359            0 :             m = 0d0
    1360              :             return
    1361              :          end if
    1362            0 :          if (abs(b) < abs(m)) m = b
    1363            0 :          if (b*c < 0d0) then
    1364            0 :             m = 0d0
    1365              :             return
    1366              :          end if
    1367            0 :          if (abs(c) < abs(m)) m = c
    1368              :       end function minmod
    1369              : 
    1370              : 
    1371            0 :       real(dp) function get1_grad(vL, vC, vR, dLeft, dCntr, dRght) &
    1372            0 :             result(grad)
    1373              :          real(dp), intent(in) :: vL, vC, vR, dLeft, dCntr, dRght
    1374            0 :          real(dp) :: sL, sR, sC
    1375              :          include 'formats'
    1376            0 :          if (dLeft <= 0d0 .or. dCntr <= 0d0 .or. dRght <= 0d0) then
    1377            0 :             grad = 0d0
    1378              :             return
    1379              :          end if
    1380            0 :          sL = (vC - vL)/dLeft
    1381            0 :          sR = (vR - vC)/dRght
    1382            0 :          sC = (vR - vL)/dCntr
    1383            0 :          grad = minmod(sL, sC, sR)
    1384            0 :       end function get1_grad
    1385              : 
    1386              : 
    1387              :       real(dp) function total_KE(s)
    1388              :          type (star_info), pointer :: s
    1389              :          integer :: k
    1390              :          include 'formats'
    1391              :          total_KE = 0
    1392              :          if (s% u_flag) then
    1393              :             do k=1,s% nz
    1394              :                total_KE = total_KE + 0.5d0*s% dm(k)*s% u(k)**2
    1395              :             end do
    1396              :          else if (s% v_flag) then
    1397              :             do k=1,s% nz-1
    1398              :                total_KE = total_KE + &
    1399              :                   0.25d0*s% dm(k)*(s% v(k)**2 + s% v(k+1)**2)
    1400              :             end do
    1401              :             k = s% nz
    1402              :             total_KE = total_KE + &
    1403              :                0.25d0*s% dm(k)*(s% v(k)**2 + s% v_center**2)
    1404              :          end if
    1405              :       end function total_KE
    1406              : 
    1407              : 
    1408              :       real(dp) function total_PE(s)
    1409              :          type (star_info), pointer :: s
    1410              :          integer :: k
    1411              :          real(dp) :: rL, rR, rC, mC
    1412              :          total_PE = 0d0
    1413              :          rR = s% R_center
    1414              :          do k = s% nz,1,-1
    1415              :             rL = rR
    1416              :             rR = s% r(k)
    1417              :             rC = 0.5d0*(rL + rR)
    1418              :             mC = s% m(k) - 0.5d0*s% dm(k)
    1419              :             total_PE = total_PE - s% cgrav(k)*mC*s% dm(k)/rC
    1420              :          end do
    1421              :       end function total_PE
    1422              : 
    1423              : 
    1424              :       real(dp) function total_IE(s)
    1425              :          type (star_info), pointer :: s
    1426              :          integer :: k
    1427              :          real(dp) :: specific_ie
    1428              :          total_IE = 0
    1429              :          do k=1,s% nz
    1430              :             specific_ie = s% energy(k)
    1431              :             total_IE = total_IE + specific_ie*s% dm(k)
    1432              :          end do
    1433              :       end function total_IE
    1434              : 
    1435              : 
    1436              :       subroutine report_energies(s, str)
    1437              :          type (star_info), pointer :: s
    1438              :          character (len=*), intent(in) :: str
    1439            0 :          real(dp) :: KE, IE, PE, Etot
    1440              :          include 'formats'
    1441              : 
    1442              :          return
    1443              : 
    1444              : 
    1445              :          KE = total_KE(s)
    1446              :          IE = total_IE(s)
    1447              :          PE = total_PE(s)
    1448              :          Etot = KE + IE + PE
    1449              :          write(*,1) 'Etot, KE, IE, PE ' // trim(str), Etot, KE, IE, PE
    1450              :       end subroutine report_energies
    1451              : 
    1452              : 
    1453              :       end module adjust_mesh_split_merge
    1454              : 
    1455              : 
        

Generated by: LCOV version 2.0-1