LCOV - code coverage report
Current view: top level - star/private - mesh_adjust.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 38.1 % 1134 432
Test Date: 2026-11-11 22:04:34 Functions: 56.7 % 30 17

            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 mesh_adjust
      21              : 
      22              :       use const_def, only: dp, ln10, one_third, four_thirds_pi
      23              :       use star_private_def
      24              :       use chem_def
      25              :       use interp_1d_def, only: pm_work_size
      26              :       use utils_lib
      27              :       use star_utils, only: get_r_from_xh, store_r_in_xh, store_rho_in_xh, &
      28              :          get_lnT_from_xh, store_lnT_in_xh, store_lnd_in_xh
      29              : 
      30              :       implicit none
      31              : 
      32              :       private
      33              :       public :: do_mesh_adjust, do_prune_mesh_surface, &
      34              :          set_lnT_for_energy_with_tol, set_lnT_for_energy
      35              : 
      36              :       integer, parameter :: nwork = pm_work_size
      37              : 
      38              :       real(dp), parameter :: eta_limit = -1d-6
      39              : 
      40              : 
      41              :       logical, parameter :: dbg = .false.
      42              : 
      43              :       contains
      44              : 
      45           10 :       subroutine do_mesh_adjust( &
      46              :             s, nz, nz_old, xh_old, xa_old, &
      47              :             energy_old, eta_old, lnd_old, lnPgas_old, &
      48              :             j_rot_old, i_rot_old, omega_old, D_omega_old, &
      49              :             mlt_vc_old, lnT_old, w_old, specific_PE_old, specific_KE_old, &
      50              :             old_m, old_r, old_rho, dPdr_dRhodr_info_old, D_mix_old, &
      51           10 :             cell_type, comes_from, dq_old, xq_old, xh, xa, dq, xq, ierr)
      52              :          use chem_lib, only: basic_composition_info
      53              :          use interp_1d_def
      54              :          use interp_1d_lib
      55              :          use star_utils, only: set_m_grav_and_grav
      56              :          use auto_diff_support
      57              :          type (star_info), pointer :: s
      58              :          integer, intent(in) :: nz, nz_old
      59              :          integer, dimension(:) :: cell_type, comes_from
      60              :          real(dp), dimension(:), pointer :: &
      61              :             dq_old, xq_old, dq, xq, energy_old, eta_old, &
      62              :             lnd_old, lnPgas_old, mlt_vc_old, lnT_old, w_old, &
      63              :             specific_PE_old, specific_KE_old, &
      64              :             old_m, old_r, old_rho, dPdr_dRhodr_info_old, &
      65              :             j_rot_old, omega_old, D_omega_old, D_mix_old
      66              :          type(auto_diff_real_star_order1), dimension(:), pointer :: i_rot_old
      67              :          real(dp), dimension(:,:), pointer :: xh_old, xa_old
      68              :          real(dp), dimension(:,:), pointer :: xh, xa
      69              :          integer, intent(out) :: ierr
      70              : 
      71              :          real(dp) :: dxa, xmstar, mstar, sumx, j_rot_center, &
      72              :             total_internal_energy1, total_internal_energy2, err
      73              :          character (len=strlen) :: message
      74              :          integer :: k, j, op_err, nzlo, nzhi, nzlo_old, nzhi_old, species
      75           10 :          real(dp), pointer :: work(:)
      76              :          real(dp), dimension(:), allocatable :: &
      77           10 :             dqbar, dqbar_old, new_r, Vol_new, xq_old_plus1, &
      78           10 :             xout_old, xout_new, xq_new, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, &
      79           10 :             energy_new, density_new
      80           10 :          real(dp), dimension(:,:), allocatable :: xa_c0, xa_c1, xa_c2
      81              : 
      82              :          include 'formats'
      83              : 
      84           10 :          ierr = 0
      85           10 :          species = s% species
      86              : 
      87           10 :          xmstar = s% xmstar
      88           10 :          mstar = xmstar + s% M_center
      89              : 
      90              :          ! check xq's
      91        10633 :          do k=1,nz
      92        10633 :             if (xq(k) < 0 .or. xq(k) > 1) then
      93            0 :                ierr = -1
      94            0 :                return
      95              : 
      96              :                write(*,*) 'k', k
      97              :                write(*,*) 'xq(k)', xq(k)
      98              :                call mesa_error(__FILE__,__LINE__,'debug: do_mesh_adjust')
      99              :             end if
     100              :          end do
     101              : 
     102              :          if (dbg) write(*,*) 'enter do_mesh_adjust'
     103              : 
     104           10 :          nzlo = 0
     105         8446 :          do k = 1, nz
     106         8446 :             if (cell_type(k) /= unchanged_type) then
     107              :                if (dbg) write(*,2) 'nzlo changed', k
     108            4 :                nzlo = k; exit
     109              :             end if
     110              :          end do
     111           10 :          if (nzlo == 0) then
     112              :             if (dbg) write(*,2) 'no cells changed'
     113            6 :             nzlo = nz
     114              :          end if
     115              : 
     116           10 :          nzhi = nzlo
     117          252 :          do k = nz, nzlo, -1
     118          252 :             if (cell_type(k) /= unchanged_type) then
     119              :                if (dbg) write(*,2) 'nzhi changed', k
     120            4 :                nzhi = k; exit
     121              :             end if
     122              :          end do
     123              : 
     124              :          ! extend range for purposes of interpolation
     125           10 :          if (nzhi < nz) nzhi = nzhi+1
     126           10 :          if (nzlo > 1) nzlo = nzlo-1
     127              : 
     128           10 :          nzlo_old = comes_from(nzlo)
     129           10 :          if (nzhi == nz) then
     130            6 :             nzhi_old = nz_old
     131              :          else
     132            4 :             nzhi_old = comes_from(nzhi+1)
     133              :          end if
     134              : 
     135           10 :          call do_alloc(ierr)
     136           10 :          if (ierr /= 0) return
     137              : 
     138        10613 :          do k=2,nz-1
     139        10613 :             dqbar(k) = 0.5d0*(dq(k-1) + dq(k))
     140              :          end do
     141           10 :          dqbar(1) = 0.5d0*dq(1)
     142           10 :          dqbar(nz) = 0.5d0*dq(nz-1) + dq(nz)
     143              : 
     144        12085 :          do k=2,nz_old-1
     145        12085 :             dqbar_old(k) = 0.5d0*(dq_old(k-1) + dq_old(k))
     146              :          end do
     147           10 :          dqbar_old(1) = 0.5d0*dq_old(1)
     148           10 :          dqbar_old(nz_old) = 0.5d0*dq_old(nz_old-1) + dq_old(nz_old)
     149              : 
     150        12105 :          do k=1,nz_old
     151        12105 :             xq_old_plus1(k) = xq_old(k)
     152              :          end do
     153              :          ! add point at true center so can interpolate xq_new > xq_old(nz_old)
     154           10 :          xq_old_plus1(nz_old+1) = 1
     155              : 
     156         1981 :          do k = 1, nzhi - nzlo + 1
     157         1981 :             xq_new(k) = xq(nzlo+k-1)
     158              :          end do
     159              : 
     160           10 :          xout_old(1) = xq_old(1)
     161        12095 :          do k=2,nz_old
     162        12095 :             xout_old(k) = xout_old(k-1) + dqbar_old(k-1)
     163              :          end do
     164              : 
     165           10 :          xout_new(1) = xq(1)
     166        10623 :          do k=2,nz
     167        10623 :             xout_new(k) = xout_new(k-1) + dqbar(k-1)
     168              :          end do
     169              : 
     170              :          if (dbg) write(*,*) 'call do_L'
     171              :          call do_L( &
     172              :             s, nz, nz_old, nzlo, nzhi, comes_from, &
     173              :             xh, xh_old, xq, xq_old_plus1, xq_new, &
     174           10 :             work, tmp1, tmp2, ierr)
     175            0 :          if (failed('do_L')) return
     176              : 
     177           10 :          if (s% RTI_flag) then
     178              :             if (dbg) write(*,*) 'call do_alpha_RTI'
     179              :             call do_alpha_RTI( &
     180              :                s, nz, nz_old, nzlo, nzhi, comes_from, &
     181              :                xh, xh_old, xq, xq_old_plus1, xq_new, &
     182            0 :                work, tmp1, tmp2, ierr)
     183            0 :             if (failed('do_alpha_RTI')) return
     184              :             call do_interp_pt_val( &
     185              :                s, nz, nz_old, nzlo, nzhi, s% dPdr_dRhodr_info, dPdr_dRhodr_info_old, &
     186            0 :                0d0, xq, xq_old_plus1, xq_new, .true., work, tmp1, tmp2, ierr)
     187            0 :             if (failed('dPdr_dRhodr_info')) return
     188              :          end if
     189              : 
     190              :          if (dbg) write(*,*) 'call do_lnR_and_lnd'
     191              :          call do_lnR_and_lnd( &
     192              :             s, nz, nz_old, nzlo, nzhi, cell_type, comes_from, &
     193              :             xh, xh_old, xmstar, lnd_old, lnPgas_old, &
     194              :             dqbar, dqbar_old, old_r, old_m, old_rho, &
     195              :             dq, dq_old, xq, xq_old_plus1, density_new, work, &
     196           10 :             tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, ierr)
     197            0 :          if (failed('do_lnR_and_lnd')) return
     198              : 
     199           10 :          if (s% v_flag) then  ! calculate new v to conserve kinetic energy
     200              :             if (dbg) write(*,*) 'call do_v'
     201              :             call do_v( &
     202              :                s, nz, nz_old, cell_type, comes_from, &
     203              :                xq_old, xq, dq_old, dq, xh, xh_old, &
     204            0 :                xout_old, xout_new, dqbar_old, dqbar, tmp1, ierr)
     205            0 :             if (failed('do_v')) return
     206              :          end if
     207              : 
     208           10 :          if (s% u_flag) then  ! calculate new u to conserve kinetic energy
     209              :             if (dbg) write(*,*) 'call do_u'
     210              :             call do_u( &
     211              :                s, nz, nz_old, cell_type, comes_from, &
     212              :                xq_old, xq, dq_old, dq, xh, xh_old, &
     213            0 :                xout_old, xout_new, tmp1, ierr)
     214            0 :             if (failed('do_u')) return
     215              :          end if
     216              : 
     217           10 :          if (s% RSP2_flag) then  ! calculate new etrb to conserve turbulent energy
     218              :             if (dbg) write(*,*) 'call do_etrb'
     219              :             call do_etrb( &
     220              :                s, nz, nz_old, cell_type, comes_from, &
     221              :                xq_old, xq, dq_old, dq, xh, xh_old, &
     222            0 :                xout_old, xout_new, tmp1, ierr)
     223            0 :             if (failed('do_etrb')) return
     224              :             if (dbg) write(*,*) 'call do_Hp_face'
     225              :             call do_Hp_face( &
     226              :                s, nz, nz_old, nzlo, nzhi, comes_from, &
     227              :                xh, xh_old, xq, xq_old_plus1, xq_new, &
     228            0 :                work, tmp1, tmp2, ierr)
     229            0 :             if (failed('do_Hp_face')) return
     230              :          end if
     231              : 
     232           10 :          if (s% rotation_flag) then
     233              :             ! adjust_omega needs i_rot before it can set omega = j_rot/i_rot
     234              :             ! in tidal binaries i_rot depends on omega, so interpolate omega to the new mesh first
     235              :             call do_interp_pt_val( &
     236              :                s, nz, nz_old, nzlo, nzhi, s% omega, omega_old, omega_old(nz_old), &
     237            0 :                xq, xq_old_plus1, xq_new, .false., work, tmp1, tmp2, ierr)
     238            0 :             if (failed('omega')) return
     239            0 :             j_rot_center = j_rot_old(nz_old)
     240            0 :             if (s% R_center == 0d0) j_rot_center = 0d0
     241              :             call do_interp_pt_val( &
     242              :                s, nz, nz_old, nzlo, nzhi, s% j_rot, j_rot_old, j_rot_center, &
     243            0 :                xq, xq_old_plus1, xq_new, .false., work, tmp1, tmp2, ierr)
     244            0 :             if (failed('j_rot')) return
     245              :             call adjust_omega(s, nz, nz_old, nzlo, nzhi, j_rot_old, &
     246            0 :                dq_old, dq, dqbar_old, dqbar, ierr)
     247            0 :             if (failed('adjust_omega')) return
     248            0 :             if (s% D_omega_flag) then
     249              :                call do_interp_pt_val( &
     250              :                   s, nz, nz_old, nzlo, nzhi, s% D_omega, D_omega_old, &
     251            0 :                   0d0, xq, xq_old_plus1, xq_new, .true., work, tmp1, tmp2, ierr)
     252            0 :                if (failed('D_omega')) return
     253              :             end if
     254              :          end if
     255              : 
     256              :          call do_interp_pt_val( &
     257              :             s, nz, nz_old, nzlo, nzhi, s% mlt_vc, mlt_vc_old, &
     258           20 :             0d0, xq, xq_old_plus1, xq_new, .true., work, tmp1, tmp2, ierr)
     259            0 :          if (failed('mlt_cv')) return
     260              : 
     261              :          call do_interp_pt_val( &
     262              :             s, nz, nz_old, nzlo, nzhi, s% D_mix, D_mix_old, &
     263           20 :             0d0, xq, xq_old_plus1, xq_new, .true., work, tmp1, tmp2, ierr)
     264            0 :          if (failed('D_mix')) return
     265              : 
     266         3457 :          do k=nzlo_old,nzhi_old  ! 1,nz_old  !
     267              : 
     268              :             ! since we must adjust things to make the sum of xa's = 1,
     269              :             ! only do linear reconstruction.
     270        31023 :             do j=1,species
     271              :                call get1_lpp(k, species, nz_old, j, dq_old, xa_old, &
     272        31023 :                               .false., xa_c0(:,j), xa_c1(:,j), xa_c2(:,j))
     273              :             end do
     274              : 
     275        31023 :             sumx = sum(xa_old(1:species,k))
     276        31023 :             do j=1,species
     277        27576 :                xa_c0(k,j) = xa_old(j,k)/sumx  ! make sure that adds to 1
     278        31023 :                xa_c2(k,j) = 0  ! no curvature terms
     279              :             end do
     280              : 
     281              :             ! only reduce magnitude of slopes
     282              :             ! so don't risk producing values out of [0..1] range
     283        31023 :             if (sum(xa_c1(k,:)) > 0) then
     284        14175 :                j = maxloc(xa_c1(k,:), dim=1)
     285              :             else
     286        16848 :                j = minloc(xa_c1(k,:), dim=1)
     287              :             end if
     288         3447 :             xa_c1(k,j) = 0
     289        31023 :             xa_c1(k,j) = -sum(xa_c1(k,:))
     290              :             ! check for valid fractions at boundaries; set slopes to 0 if find a bad one.
     291        31033 :             do j=1,species
     292        27576 :                dxa = abs(xa_c1(k,j))*dq_old(k)/2
     293        31023 :                if (xa_c0(k,j) + dxa > 1 .or. xa_c0(k,j) - dxa < 0) then
     294            0 :                   xa_c1(k,:) = 0
     295              :                   exit
     296              :                end if
     297              :             end do
     298              : 
     299              :          end do
     300              : 
     301            0 :          if (failed('adjust_mesh nz_old parallel loop')) return
     302              : 
     303              :          if (dbg) write(*,*) 'do xa and lnT'
     304              : 
     305              :          total_internal_energy1 = &
     306        12105 :             dot_product(dq_old(1:nz_old), energy_old(1:nz_old))
     307              : 
     308        10633 :          do k = 1, nz
     309              : 
     310              :             op_err = 0
     311              : 
     312              :             ! calculate new abundances to conserve species
     313              :             call do_xa( &
     314              :                s, nz, nz_old, k, species, cell_type, comes_from, xa, xa_old, &
     315              :                xa_c0, xa_c1, xa_c2, xq, dq, xq_old, dq_old, &
     316        10623 :                .true., op_err)
     317        10633 :             if (op_err /= 0) then
     318            0 :                write(*,2) 'failed for do_xa', k
     319            0 :                stop
     320              :                write(message,*) 'do_xa for k', k
     321              :                ierr = op_err
     322              :             end if
     323              : 
     324              :          end do
     325              : 
     326              :          ! ensure the things we need to calculate m_grav and grav are up to date
     327        10633 :          do k = 1, nz
     328              : 
     329              :             op_err = 0
     330              : 
     331              :             ! ensure that mass corrections are up to date
     332              :             call basic_composition_info( &
     333              :                  species, s% chem_id, xa(1:species,k), s% X(k), s% Y(k), s% Z(k), &
     334              :                  s% abar(k), s% zbar(k), s% z2bar(k), s% z53bar(k), &
     335        10623 :                  s% ye(k), s% mass_correction(k), sumx)
     336              : 
     337              :             ! ensure that r is up to date
     338        10633 :             s% r(k) = exp(s% xh(s% i_lnr,k))
     339              : 
     340              :          end do
     341              : 
     342              :          ! needed because do1_lnT evaluates PE
     343           10 :          call set_m_grav_and_grav(s)
     344              : 
     345        10633 :          do k = 1, nz
     346              : 
     347              :             op_err = 0
     348              : 
     349              :             ! calculate new temperatures to conserve energy
     350              :             call do1_lnT( &
     351              :                s, nz_old, k, species, cell_type, comes_from, &
     352              :                xa, xh, xh_old, &
     353              :                xq, dq, xq_old, dq_old, eta_old, energy_old, lnT_old, &
     354              :                specific_PE_old, specific_KE_old, w_old, &
     355        10623 :                density_new, energy_new, op_err)
     356        10623 :             if (op_err /= 0) then
     357            0 :                write(*,2) 'failed for do1_lnT', k
     358            0 :                write(message,*) 'do1_lnT for k', k
     359            0 :                ierr = op_err
     360            0 :                call mesa_error(__FILE__,__LINE__,'mesh adjust: do1_lnT')
     361              :             end if
     362        10633 :             if (is_bad(energy_new(k)) .or. is_bad(dq(k))) then
     363            0 :                write(*,2) 'energy_new', k, energy_new(k)
     364            0 :                write(*,2) 'dq', k, dq(k)
     365            0 :                call mesa_error(__FILE__,__LINE__,'mesh adjust: bad energy_new or dq')
     366              :             end if
     367              : 
     368              :          end do
     369              : 
     370            0 :          if (failed(message)) return
     371              : 
     372        10633 :          total_internal_energy2 = dot_product(dq(1:nz), energy_new(1:nz))
     373              :          err = abs(total_internal_energy1 - total_internal_energy2)/ &
     374           10 :                max(abs(total_internal_energy1),abs(total_internal_energy2),1d0)
     375           10 :          s% mesh_adjust_IE_conservation = err
     376              : 
     377           10 :          if (s% trace_mesh_adjust_error_in_conservation) then
     378              : 
     379            0 :             write(*,2) 'mesh adjust error in conservation of IE', &
     380            0 :                s% model_number, err, total_internal_energy2, total_internal_energy1
     381            0 :             if (err > 1d-8) then
     382            0 :                call show_errors
     383            0 :                write(*,*) 'err too large'
     384            0 :                call mesa_error(__FILE__,__LINE__,'mesh adjust')
     385              :             end if
     386              : 
     387              :          end if
     388              : 
     389              :          if (dbg) write(*,*) 'call check_species_conservation'
     390           10 :          call check_species_conservation(species,ierr)
     391           10 :          if (ierr /= 0) then
     392            0 :             write(*,*) 'failed in check_species_conservation'
     393            0 :             stop
     394              :          end if
     395              : 
     396           10 :          call dealloc
     397              : 
     398              :          contains
     399              : 
     400            0 :          subroutine show_errors
     401              :             integer :: k0, k0_from, k, k_from, k_outer
     402              :             real(dp) :: new_sum, old_sum
     403              : 
     404              :             include 'formats'
     405              : 
     406              :             k0 = 1
     407              :             k0_from = 1
     408            0 :             k_outer = 2
     409            0 :             write(*,'(A)')
     410              :             do
     411            0 :                if (cell_type(k_outer) == unchanged_type .and. k_outer /= nz) then
     412            0 :                   k_outer = k_outer + 1
     413            0 :                   cycle
     414              :                end if
     415            0 :                k0 = k_outer
     416            0 :                k0_from = comes_from(k_outer)
     417            0 :                do k = k0+1, nz
     418            0 :                   if (cell_type(k) /= unchanged_type .and. k /= nz) cycle
     419            0 :                   new_sum = dot_product(dq(k0:k),energy_new(k0:k))
     420            0 :                   k_from = comes_from(k)
     421              :                   old_sum = &
     422            0 :                      dot_product(dq_old(k0_from:k_from),energy_old(k0_from:k_from))
     423            0 :                   write(*,5) 'section err', k0, k, k0_from, k_from, &
     424            0 :                      abs(old_sum - new_sum)/max(abs(old_sum),abs(new_sum),1d0), &
     425            0 :                      old_sum, new_sum
     426            0 :                   k_outer = k
     427            0 :                   exit
     428              :                end do
     429            0 :                if (k_outer == nz) exit
     430            0 :                k_outer = k_outer + 1
     431              :             end do
     432            0 :             write(*,2) 'nz_old', nz_old
     433            0 :             write(*,2) 'nz', nz
     434            0 :             write(*,'(A)')
     435              : 
     436            0 :          end subroutine show_errors
     437              : 
     438           10 :          subroutine do_alloc(ierr)
     439              :             integer, intent(out) :: ierr
     440              :             integer :: sz
     441           10 :             sz = max(nz, nz_old) + 1
     442           10 :             call do_work_arrays(.true.,ierr)
     443              :             allocate( &
     444            0 :                dqbar(sz), dqbar_old(sz), new_r(sz), Vol_new(sz), xq_old_plus1(sz), &
     445            0 :                xout_old(sz), xout_new(sz), xq_new(sz), energy_new(sz), density_new(sz), &
     446            0 :                tmp1(sz), tmp2(sz), tmp3(sz), tmp4(sz), tmp5(sz), tmp6(sz), tmp7(sz), &
     447          260 :                xa_c0(sz,species), xa_c1(sz,species), xa_c2(sz,species))
     448           10 :          end subroutine do_alloc
     449              : 
     450           10 :          subroutine dealloc
     451           10 :             call do_work_arrays(.false.,ierr)
     452              :          end subroutine dealloc
     453              : 
     454           20 :          subroutine do_work_arrays(alloc_flag, ierr)
     455              :             use interp_1d_def
     456              :             use alloc
     457              :             logical, intent(in) :: alloc_flag
     458              :             integer, intent(out) :: ierr
     459              :             logical, parameter :: crit = .false.
     460              :             ierr = 0
     461              :             call work_array(s, alloc_flag, crit, &
     462           20 :                 work, (nz_old+1)*pm_work_size, nz_alloc_extra, 'mesh_adjust', ierr)
     463              :             if (ierr /= 0) return
     464              :          end subroutine do_work_arrays
     465              : 
     466              : 
     467           60 :          logical function failed(msg)
     468              :             character (len=*) :: msg
     469           60 :             if (ierr == 0) then
     470           60 :                failed = .false.
     471              :                return
     472              :             end if
     473            0 :             failed = .true.
     474              :             if (dbg) write(*, *) 'mesh_revisions failed in ' // trim(msg)
     475              :             call dealloc
     476              :             return
     477              :          end function failed
     478              : 
     479              : 
     480           10 :          subroutine check_species_conservation(species,ierr)
     481              :             integer, intent(in) :: species
     482              :             integer, intent(out) :: ierr
     483              :             integer :: j, k, jbad
     484              :             real(dp) :: old_total, new_total
     485              :             logical :: okay
     486              :             include 'formats'
     487           10 :             ierr = 0
     488           10 :             okay = .true.
     489           10 :             jbad = -1
     490           90 :             do j=1,species
     491        96840 :                old_total = dot_product(xa_old(j,1:nz_old),dq_old(1:nz_old))
     492           80 :                if (old_total < 1d-9) cycle
     493        85064 :                new_total = dot_product(xa(j,1:nz),dq(1:nz))
     494           90 :                if (abs(new_total - old_total) > 1d-4) then  ! check for major problems
     495            0 :                   ierr = -1
     496            0 :                   jbad = j
     497            0 :                   okay = .false.
     498              :                   if (dbg) then
     499              :                      write(*,*) 'problem with conservation of species ' //  &
     500              :                         chem_isos% name(s% chem_id(j))
     501              :                      write(*,1) 'new mass fraction', new_total
     502              :                      write(*,1) 'old mass fraction', old_total
     503              :                      write(*,1) 'new - old', new_total - old_total
     504              :                      write(*,1) '(new - old)/old', (new_total - old_total) / old_total
     505              :                      write(*,'(A)')
     506              :                   end if
     507              :                end if
     508              :             end do
     509           10 :             if (okay) return
     510            0 :             ierr = -1
     511            0 :             write(*,'(A)')
     512            0 :             do j=1,species
     513            0 :                old_total = dot_product(xa_old(j,1:nz_old),dq_old(1:nz_old))
     514            0 :                if (old_total < 1d-9) cycle
     515            0 :                new_total = dot_product(xa(j,1:nz),dq(1:nz))
     516            0 :                write(*,2) 'new - old mass fraction ' // chem_isos% name(s% chem_id(j)), &
     517            0 :                      j, new_total-old_total
     518              :             end do
     519            0 :             write(*,'(A)')
     520            0 :             j = jbad
     521            0 :             do k=2, nz
     522            0 :                if (comes_from(k) == comes_from(k-1)) cycle
     523            0 :                old_total = dot_product(xa_old(j,1:comes_from(k)-1),dq_old(1:comes_from(k)-1))
     524            0 :                if (old_total < 1d-9) cycle
     525            0 :                new_total = dot_product(xa(j,1:k-1),dq(1:k-1))
     526            0 :                write(*,2) 'partial new - old ' // chem_isos% name(s% chem_id(j)), k, &
     527            0 :                   new_total-old_total, new_total, old_total
     528              :             end do
     529            0 :             write(*,'(A)')
     530            0 :             do k=415, nz
     531            0 :                write(*,'(a30,99i6)') 'cell_type(k)', k, cell_type(k), comes_from(k)
     532              :             end do
     533            0 :             write(*,'(A)')
     534            0 :             write(*,2) 'xq', 439, xq(439)
     535            0 :             write(*,2) 'xq_old', 429, xq_old(429)
     536            0 :             write(*,2) 'dq_old', 429, dq_old(429)
     537            0 :             write(*,2) 'dq', 439, dq(439)
     538            0 :             write(*,'(A)')
     539            0 :             write(*,2) 'xq', 424, xq(424)
     540            0 :             write(*,2) 'xq_old', 428, xq_old(428)
     541            0 :             write(*,2) 'dq_old', 428, dq_old(428)
     542            0 :             write(*,2) 'sum dq', 424, sum(dq(424:438))
     543            0 :             write(*,'(A)')
     544            0 :             write(*,2) 'xq_old + dq_old', 428, xq_old(428) + dq_old(428)
     545            0 :             write(*,2) 'xq_old', 429, xq_old(429)
     546            0 :             write(*,'(A)')
     547            0 :             write(*,2) 'xq + sum dq', 424, xq(424) + sum(dq(424:438))
     548            0 :             write(*,2) 'xq', 439, xq(439)
     549            0 :             write(*,'(A)')
     550            0 :             write(*,1) 'sum dq_old', sum(dq_old(1:nz_old))
     551              : 
     552            0 :             write(*,2) 'dq_old', 427, dq_old(427)
     553            0 :             write(*,2) 'sum new', 416, sum(dq(416:423))
     554            0 :             write(*,2) 'dq_old - sum new', 427, dq_old(427) - sum(dq(416:423))
     555            0 :             write(*,2) 'dq_old', 428, dq_old(428)
     556            0 :             write(*,2) 'sum new', 424, sum(dq(424:438))
     557            0 :             write(*,2) 'dq_old - sum new', 428, dq_old(428) - sum(dq(424:438))
     558              :          end subroutine check_species_conservation
     559              : 
     560              : 
     561              :       end subroutine do_mesh_adjust
     562              : 
     563              : 
     564            0 :       subroutine do_prune_mesh_surface( &
     565              :             s, nz, nz_old, xh_old, xa_old, &
     566              :             j_rot_old, i_rot_old, omega_old, D_omega_old, am_nu_rot_old, &
     567              :             mlt_vc_old, lnT_old, &
     568              :             dPdr_dRhodr_info_old, nu_ST_old, D_ST_old, D_DSI_old, D_SH_old, &
     569              :             D_SSI_old, D_ES_old, D_GSF_old, D_mix_old, &
     570              :             xh, xa, ierr)
     571              :          use auto_diff_support
     572              :          type (star_info), pointer :: s
     573              :          integer, intent(in) :: nz, nz_old
     574              :          real(dp), dimension(:), pointer :: &
     575              :             j_rot_old, omega_old, &
     576              :             D_omega_old, am_nu_rot_old, mlt_vc_old, lnT_old, &
     577              :             dPdr_dRhodr_info_old, nu_ST_old, D_ST_old, D_DSI_old, D_SH_old, &
     578              :             D_SSI_old, D_ES_old, D_GSF_old, D_mix_old
     579              :          type(auto_diff_real_star_order1), dimension(:), pointer :: i_rot_old
     580              :          real(dp), dimension(:,:), pointer :: xh_old, xa_old
     581              :          real(dp), dimension(:,:), pointer :: xh, xa
     582              :          integer, intent(out) :: ierr
     583              : 
     584              :          integer :: skip, k, k_old, j
     585              : 
     586              :          include 'formats'
     587              : 
     588            0 :          ierr = 0
     589            0 :          skip = nz_old - nz
     590            0 :          if (skip < 0) then
     591            0 :             write(*,3) 'bad nz prune_surface do_prune_mesh_surface', nz_old, nz
     592            0 :             ierr = -1
     593            0 :             return
     594              :          end if
     595              : 
     596            0 :          do k = 1, nz
     597            0 :             k_old = k + skip
     598            0 :             do j = 1, s% nvar_hydro
     599            0 :                xh(j,k) = xh_old(j,k_old)
     600              :             end do
     601            0 :             do j = 1, s% species
     602            0 :                xa(j,k) = xa_old(j,k_old)
     603              :             end do
     604              :          end do
     605              : 
     606            0 :          call prune1(s% lnT, lnT_old, skip)
     607            0 :          call prune1(s% D_mix, D_mix_old, skip)
     608            0 :          call prune1(s% mlt_vc, mlt_vc_old, skip)
     609              : 
     610            0 :          if (s% rotation_flag) then
     611            0 :             call prune1(s% j_rot, j_rot_old, skip)
     612            0 :             call prune1_ad(s% i_rot, i_rot_old, skip)
     613            0 :             call prune1(s% omega, omega_old, skip)
     614            0 :             call prune1(s% nu_ST, nu_ST_old, skip)
     615            0 :             call prune1(s% D_ST, D_ST_old, skip)
     616            0 :             call prune1(s% D_DSI, D_DSI_old, skip)
     617            0 :             call prune1(s% D_SH, D_SH_old, skip)
     618            0 :             call prune1(s% D_SSI, D_SSI_old, skip)
     619            0 :             call prune1(s% D_ES, D_ES_old, skip)
     620            0 :             call prune1(s% D_GSF, D_GSF_old, skip)
     621              :          end if
     622              : 
     623            0 :          if (s% D_omega_flag) then
     624            0 :             call prune1(s% D_omega, D_omega_old, skip)
     625              :          end if
     626              : 
     627            0 :          if (s% RTI_flag) then
     628            0 :             call prune1(s% dPdr_dRhodr_info, dPdr_dRhodr_info_old, skip)
     629              :          end if
     630              : 
     631              :          contains
     632              : 
     633            0 :          subroutine prune1(p,p_old,skip)
     634              :             real(dp), dimension(:), pointer :: p, p_old
     635              :             integer, intent(in) :: skip
     636              :             integer :: k
     637            0 :             do k=1,nz
     638            0 :                p(k) = p_old(k+skip)
     639              :             end do
     640            0 :          end subroutine prune1
     641              : 
     642            0 :          subroutine prune1_ad(p,p_old,skip)
     643              :             type(auto_diff_real_star_order1), dimension(:), pointer :: p, p_old
     644              :             integer, intent(in) :: skip
     645              :             integer :: k
     646            0 :             do k=1,nz
     647            0 :                p(k) = p_old(k+skip)
     648              :             end do
     649            0 :          end subroutine prune1_ad
     650              : 
     651              :       end subroutine do_prune_mesh_surface
     652              : 
     653              : 
     654              :       subroutine do_xh_pt_var( &
     655              :             s, i_var, nz, nz_old, nzlo, nzhi, comes_from, xh, xh_old, center_val, &
     656              :             xq, xq_old_plus1, xq_new, work, var_old_plus1, var_new, ierr)
     657              :          use interp_1d_def
     658              :          use interp_1d_lib
     659              :          type (star_info), pointer :: s
     660              :          integer, intent(in) :: i_var, nz, nz_old, nzlo, nzhi, comes_from(:)
     661              :          real(dp),intent(in) :: center_val
     662              :          real(dp), dimension(:,:), pointer :: xh, xh_old
     663              :          real(dp), dimension(:), pointer :: work
     664              :          real(dp), dimension(:) :: &
     665              :             xq, xq_old_plus1, var_old_plus1, var_new, xq_new
     666              :          integer, intent(out) :: ierr
     667              : 
     668              :          integer :: n, k
     669              : 
     670              :          include 'formats'
     671              : 
     672              :          ierr = 0
     673              :          n = nzhi - nzlo + 1
     674              : 
     675              :          do k=1,nz_old
     676              :             var_old_plus1(k) = xh_old(i_var,k)
     677              :          end do
     678              :          var_old_plus1(nz_old+1) = center_val
     679              : 
     680              :          call interpolate_vector( &
     681              :             nz_old+1, xq_old_plus1, n, xq_new, &
     682              :             var_old_plus1, var_new, interp_pm, nwork, work, &
     683              :             'mesh_adjust do_xh_pt_var', ierr)
     684              :          if (ierr /= 0) then
     685              :             return
     686              :          end if
     687              : 
     688              :          do k=nzlo,nzhi
     689              :             xh(i_var,k) = max(0d0,var_new(k+1-nzlo))
     690              :          end do
     691              : 
     692              :          n = nzlo - 1
     693              :          if (n > 0) then
     694              :             do k=1,n
     695              :                xh(i_var,k) = xh_old(i_var,k)
     696              :             end do
     697              :          end if
     698              : 
     699              :          if (nzhi < nz) then
     700              :             n = nz - nzhi - 1  ! nz-n = nzhi+1
     701              :             do k=0,n
     702              :                xh(i_var,nz-k) = xh_old(i_var,nz_old-k)
     703              :             end do
     704              :          end if
     705              : 
     706              :       end subroutine do_xh_pt_var
     707              : 
     708              : 
     709           10 :       subroutine do_L( &
     710              :             s, nz, nz_old, nzlo, nzhi, comes_from, xh, xh_old, &
     711           10 :             xq, xq_old_plus1, xq_new, work, L_old_plus1, L_new, ierr)
     712              :          use interp_1d_def
     713              :          use interp_1d_lib
     714              :          type (star_info), pointer :: s
     715              :          integer, intent(in) :: nz, nz_old, nzlo, nzhi, comes_from(:)
     716              :          real(dp), dimension(:,:), pointer :: xh, xh_old
     717              :          real(dp), dimension(:), pointer :: work
     718              :          real(dp), dimension(:) :: &
     719              :             xq, xq_old_plus1, L_old_plus1, L_new, xq_new
     720              :          integer, intent(out) :: ierr
     721              : 
     722              :          integer :: n, i_lum, k
     723              : 
     724              :          include 'formats'
     725              : 
     726           10 :          ierr = 0
     727           10 :          i_lum = s% i_lum
     728           10 :          if (i_lum == 0) return
     729           10 :          n = nzhi - nzlo + 1
     730              : 
     731        12105 :          do k=1,nz_old
     732        12105 :             L_old_plus1(k) = xh_old(i_lum,k)
     733              :          end do
     734           10 :          L_old_plus1(nz_old+1) = s% L_center
     735              : 
     736              :          call interpolate_vector( &
     737              :                nz_old+1, xq_old_plus1, n, xq_new, &
     738              :                L_old_plus1, L_new, interp_pm, nwork, work, &
     739           10 :                'mesh_adjust do_L', ierr)
     740           10 :          if (ierr /= 0) then
     741              :             return
     742              : 
     743              :             write(*,*) 'interpolate_vector failed in do_L for remesh'
     744              :             call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do_L')
     745              :          end if
     746              : 
     747         1981 :          do k=nzlo,nzhi
     748         1981 :             xh(i_lum,k) = L_new(k+1-nzlo)
     749              :          end do
     750              : 
     751           10 :          n = nzlo - 1
     752           10 :          if (n > 0) then
     753         8430 :             do k=1,n
     754         8430 :                xh(i_lum,k) = xh_old(i_lum,k)
     755              :             end do
     756              :          end if
     757              : 
     758           10 :          if (nzhi < nz) then
     759            4 :             n = nz - nzhi - 1  ! nz-n = nzhi+1
     760          236 :             do k=0,n
     761          236 :                xh(i_lum,nz-k) = xh_old(i_lum,nz_old-k)
     762              :             end do
     763              :          end if
     764              : 
     765              :       end subroutine do_L
     766              : 
     767              : 
     768            0 :       subroutine do_alpha_RTI( &
     769              :             s, nz, nz_old, nzlo, nzhi, comes_from, xh, xh_old, &
     770            0 :             xq, xq_old_plus1, xq_new, work, alpha_RTI_old_plus1, alpha_RTI_new, ierr)
     771              :          use interp_1d_def
     772              :          use interp_1d_lib
     773              :          type (star_info), pointer :: s
     774              :          integer, intent(in) :: nz, nz_old, nzlo, nzhi, comes_from(:)
     775              :          real(dp), dimension(:,:), pointer :: xh, xh_old
     776              :          real(dp), dimension(:), pointer :: work
     777              :          real(dp), dimension(:) :: &
     778              :             xq, xq_old_plus1, alpha_RTI_old_plus1, alpha_RTI_new, xq_new
     779              :          integer, intent(out) :: ierr
     780              : 
     781              :          integer :: n, i_alpha_RTI, k
     782              : 
     783              :          include 'formats'
     784              : 
     785              :          ierr = 0
     786            0 :          i_alpha_RTI = s% i_alpha_RTI
     787            0 :          n = nzhi - nzlo + 1
     788              : 
     789            0 :          do k=1,nz_old
     790            0 :             alpha_RTI_old_plus1(k) = xh_old(i_alpha_RTI,k)
     791              :          end do
     792            0 :          alpha_RTI_old_plus1(nz_old+1) = 0
     793              : 
     794              :          call interpolate_vector( &
     795              :                nz_old+1, xq_old_plus1, n, xq_new, &
     796              :                alpha_RTI_old_plus1, alpha_RTI_new, interp_pm, nwork, work, &
     797            0 :                'mesh_adjust do_alpha_RTI', ierr)
     798            0 :          if (ierr /= 0) then
     799            0 :             return
     800              :          end if
     801              : 
     802            0 :          do k=nzlo,nzhi
     803            0 :             xh(i_alpha_RTI,k) = max(0d0,alpha_RTI_new(k+1-nzlo))
     804              :          end do
     805              : 
     806            0 :          n = nzlo - 1
     807            0 :          if (n > 0) then
     808            0 :             do k=1,n
     809            0 :                xh(i_alpha_RTI,k) = xh_old(i_alpha_RTI,k)
     810              :             end do
     811              :          end if
     812              : 
     813            0 :          if (nzhi < nz) then
     814            0 :             n = nz - nzhi - 1  ! nz-n = nzhi+1
     815            0 :             do k=0,n
     816            0 :                xh(i_alpha_RTI,nz-k) = xh_old(i_alpha_RTI,nz_old-k)
     817              :             end do
     818              :          end if
     819              : 
     820              :       end subroutine do_alpha_RTI
     821              : 
     822              : 
     823           20 :       subroutine do_interp_pt_val( &
     824              :             s, nz, nz_old, nzlo, nzhi, val, val_old, center_val, &
     825           20 :             xq, xq_old_plus1, xq_new, force_non_negative, &
     826           40 :             work, val_old_plus1, val_new, ierr)
     827              :          use interp_1d_def
     828              :          use interp_1d_lib
     829              :          type (star_info), pointer :: s
     830              :          integer, intent(in) :: nz, nz_old, nzlo, nzhi
     831              :          real(dp), dimension(:), pointer :: val, val_old
     832              :          real(dp), intent(in) :: center_val
     833              :          real(dp), dimension(:), pointer :: work
     834              :          real(dp), dimension(:) :: &
     835              :             xq, xq_old_plus1, xq_new, val_old_plus1, val_new
     836              :          logical, intent(in) :: force_non_negative
     837              :          integer, intent(out) :: ierr
     838              :          integer :: n, k
     839              : 
     840              :          include 'formats'
     841              : 
     842              :          ierr = 0
     843           20 :          n = nzhi - nzlo + 1
     844              : 
     845        24210 :          do k=1,nz_old
     846        24210 :             val_old_plus1(k) = val_old(k)
     847              :          end do
     848           20 :          val_old_plus1(nz_old+1) = center_val
     849              : 
     850              :          call interpolate_vector( &
     851              :                nz_old+1, xq_old_plus1, n, xq_new, &
     852              :                val_old_plus1, val_new, interp_pm, nwork, work, &
     853           20 :                'mesh_adjust do_interp_pt_val', ierr)
     854           20 :          if (ierr /= 0) then
     855            0 :             return
     856              :          end if
     857              : 
     858         3962 :          do k=nzlo,nzhi
     859         3962 :             val(k) = val_new(k+1-nzlo)
     860              :          end do
     861              : 
     862           20 :          n = nzlo - 1
     863           20 :          if (n > 0) then
     864        16860 :             do k=1,n
     865        16860 :                val(k) = val_old(k)
     866              :             end do
     867              :          end if
     868              : 
     869           20 :          if (nzhi < nz) then
     870            8 :             n = nz - nzhi - 1  ! nz-n = nzhi+1
     871          472 :             do k=0,n
     872          472 :                val(nz-k) = val_old(nz_old-k)
     873              :             end do
     874              :          end if
     875              : 
     876           20 :          if (force_non_negative) then
     877         3962 :             do k=nzlo,nzhi
     878         3962 :                if (val(k) < 0) val(k) = 0
     879              :             end do
     880              :          end if
     881              : 
     882              :       end subroutine do_interp_pt_val
     883              : 
     884              : 
     885              :       subroutine do_interp_cell_val( &
     886              :             s, nz, nz_old, nzlo, nzhi, val_new_out, val_old, &
     887              :             xq, xq_old_plus1, dq, dq_old, work, val_old_plus1, val_new, ierr)
     888              :          use interp_1d_def
     889              :          use interp_1d_lib
     890              :          type (star_info), pointer :: s
     891              :          integer, intent(in) :: nz, nz_old, nzlo, nzhi
     892              :          real(dp), dimension(:), pointer :: val_new_out, val_old
     893              :          real(dp), dimension(:), pointer :: work
     894              :          real(dp), dimension(:) :: &
     895              :             xq, xq_old_plus1, dq, dq_old, val_old_plus1, val_new
     896              :          integer, intent(out) :: ierr
     897              : 
     898              :          real(dp), pointer, dimension(:) :: &
     899              :             mid_xq_new, mid_xq_old_plus1
     900              :          integer :: n, i, k
     901              : 
     902              :          ierr = 0
     903              :          n = nzhi - nzlo + 1
     904              :          call do_alloc(ierr)
     905              :          if (ierr /= 0) return
     906              : 
     907              :          do k=1,nz_old
     908              :             val_old_plus1(k) = val_old(k)
     909              :             mid_xq_old_plus1(k) = xq_old_plus1(k) + 0.5d0*dq_old(k)
     910              :          end do
     911              :          val_old_plus1(nz_old+1) = val_old_plus1(nz_old)
     912              :          mid_xq_old_plus1(nz_old+1) = 1
     913              :          do i=1,n
     914              :             mid_xq_new(i) = xq(nzlo+i-1) + 0.5d0*dq(nzlo+i-1)
     915              :          end do
     916              : 
     917              :          call interpolate_vector( &
     918              :                nz_old+1, mid_xq_old_plus1, n, mid_xq_new, &
     919              :                val_old_plus1, val_new, interp_pm, nwork, work, &
     920              :                'mesh_adjust do_interp_cell_val', ierr)
     921              :          if (ierr /= 0) then
     922              :             call dealloc
     923              :             return
     924              :          end if
     925              : 
     926              :          do i=1,n
     927              :             val_new_out(nzlo+i-1) = val_new(i)
     928              :          end do
     929              : 
     930              :          n = nzlo - 1
     931              :          if (n > 0) then
     932              :             do i=1,n
     933              :                val_new_out(i) = val_old(i)
     934              :             end do
     935              :          end if
     936              : 
     937              :          if (nzhi < nz) then
     938              :             n = nz - nzhi - 1  ! nz-n = nzhi+1
     939              :             do i=0,n
     940              :                val_new_out(nz-i) = val_old(nz_old-i)
     941              :             end do
     942              :          end if
     943              : 
     944              :          call dealloc
     945              : 
     946              :          contains
     947              : 
     948              :          subroutine do_alloc(ierr)
     949              :             integer, intent(out) :: ierr
     950              :             call do_work_arrays(.true.,ierr)
     951              :          end subroutine do_alloc
     952              : 
     953              :          subroutine dealloc
     954              :             integer :: ierr
     955              :             call do_work_arrays(.false.,ierr)
     956              :          end subroutine dealloc
     957              : 
     958              :          subroutine do_work_arrays(alloc_flag, ierr)
     959              :             use alloc, only: work_array
     960              :             logical, intent(in) :: alloc_flag
     961              :             integer, intent(out) :: ierr
     962              :             logical, parameter :: crit = .false.
     963              :             ierr = 0
     964              :             call work_array(s, alloc_flag, crit, &
     965              :                 mid_xq_old_plus1, nz_old+1, nz_alloc_extra, 'mesh_adjust', ierr)
     966              :             if (ierr /= 0) return
     967              :             call work_array(s, alloc_flag, crit, &
     968              :                 mid_xq_new, n, nz_alloc_extra, 'mesh_adjust', ierr)
     969              :             if (ierr /= 0) return
     970              :          end subroutine do_work_arrays
     971              : 
     972              :       end subroutine do_interp_cell_val
     973              : 
     974              : 
     975           10 :       subroutine do_lnR_and_lnd( &
     976           20 :             s, nz, nz_old, nzlo, nzhi, cell_type, comes_from, &
     977           10 :             xh, xh_old, xmstar, lnd_old, lnPgas_old, &
     978           10 :             dqbar, dqbar_old, old_r, old_m, old_rho, &
     979           20 :             dq, dq_old, xq, xq_old_plus1, density_new, work, &
     980           30 :             Vol_old_plus1, Vol_new, new_r, Vol_init, &
     981           20 :             interp_Vol_new, interp_xq, density_init, ierr)
     982              :          use interp_1d_def
     983              :          use interp_1d_lib
     984              :          use num_lib
     985              :          type (star_info), pointer :: s
     986              :          integer, intent(in) :: nz, nz_old, nzlo, nzhi, comes_from(:)
     987              :          integer :: cell_type(:)
     988              :          real(dp), dimension(:,:), pointer :: xh, xh_old
     989              :          real(dp), intent(in) :: xmstar
     990              :          real(dp), dimension(:), pointer :: work
     991              :          real(dp), dimension(:) :: &
     992              :             lnd_old, lnPgas_old, dqbar, dqbar_old, old_r, old_m, old_rho, &
     993              :             xq, dq, dq_old, xq_old_plus1, density_new, &
     994              :             Vol_old_plus1, Vol_new, new_r, Vol_init, &
     995              :             interp_Vol_new, interp_xq, density_init
     996              :          integer, intent(out) :: ierr
     997              : 
     998              :          integer :: k, from_k, n, interp_lo, interp_hi, interp_n
     999              :          real(dp) :: Vol_min, Vol_max, cell_Vol, Vol_center, Vm1, V00, Vp1
    1000              : 
    1001              :          logical, parameter :: dbg = .false., trace_PE_residual = .false.
    1002              : 
    1003              :          include 'formats'
    1004              : 
    1005              :          ! NOTE: for interpolating volume, need to add point at center
    1006              : 
    1007              :          ierr = 0
    1008              : 
    1009           10 :          interp_lo = max(1, nzlo-1)
    1010           10 :          interp_hi = min(nz, nzhi+1)
    1011           10 :          interp_n = interp_hi - interp_lo + 1
    1012              : 
    1013        12105 :          do k=1,nz_old
    1014        12105 :             Vol_old_plus1(k) = four_thirds_pi*old_r(k)*old_r(k)*old_r(k)
    1015              :          end do
    1016           10 :          Vol_center = four_thirds_pi*s% R_center*s% R_center*s% R_center
    1017           10 :          Vol_old_plus1(nz_old+1) = Vol_center
    1018              : 
    1019              :          ! testing -- check for Vol_old_plus1 strictly decreasing
    1020        12105 :          do k = 2, nz_old+1
    1021        12105 :             if (Vol_old_plus1(k) >= Vol_old_plus1(k-1)) then
    1022            0 :                ierr = -1
    1023            0 :                if (.not. dbg) return
    1024              :                write(*,3) 'bad old vol', k, nz_old
    1025              :                write(*,1) 'Vol_old_plus1(k)', Vol_old_plus1(k)
    1026              :                write(*,1) 'Vol_old_plus1(k-1)', Vol_old_plus1(k-1)
    1027              :                write(*,'(A)')
    1028              :                call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do_lnR_and_lnd')
    1029              :             end if
    1030              :          end do
    1031              : 
    1032              :          ! testing -- check for q strictly decreasing
    1033        10623 :          do k = 2, nz
    1034        10623 :             if (xq(k) <= xq(k-1)) then
    1035            0 :                ierr = -1
    1036            0 :                if (.not. dbg) return
    1037              : 
    1038              :                write(*,3) 'bad xq', k, nz, xq(k), xq(k-1)
    1039              :                call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do_lnR_and_lnd')
    1040              :             end if
    1041              :          end do
    1042              : 
    1043         1995 :          do k=1,interp_n
    1044         1995 :             interp_xq(k) = xq(interp_lo+k-1)
    1045              :          end do
    1046              : 
    1047              :          call interpolate_vector( &
    1048              :                nz_old+1, xq_old_plus1, interp_n, interp_xq, Vol_old_plus1, &
    1049           10 :                interp_Vol_new, interp_pm, nwork, work, 'mesh_adjust do_lnR_and_lnd', ierr)
    1050           10 :          if (ierr /= 0) then
    1051              :             if (.not. dbg) return
    1052              :             write(*,*) 'failed in interpolate_vector'
    1053              :             call mesa_error(__FILE__,__LINE__,'debug: mesh_adjust')
    1054              :          end if
    1055              : 
    1056         1995 :          do k=1,interp_n
    1057         1995 :             Vol_new(interp_lo+k-1) = interp_Vol_new(k)
    1058              :          end do
    1059              : 
    1060           10 :          if (Vol_new(interp_lo+1) >= Vol_new(interp_lo)) then
    1061            0 :             Vol_new(interp_lo+1) = (Vol_new(interp_lo) + Vol_new(interp_lo+2))/2
    1062              :             if (dbg) write(*,2) 'fix Vol_new at lo+1', interp_lo+1, Vol_new(interp_lo+1)
    1063            0 :             if (Vol_new(interp_lo+1) >= Vol_new(interp_lo)) then
    1064            0 :                ierr = -1
    1065            0 :                if (.not. dbg) return
    1066              :                write(*,*) '(Vol_new(interp_lo+1) >= Vol_new(interp_lo))'
    1067              :                call mesa_error(__FILE__,__LINE__,'debug: mesh_adjust')
    1068              :             end if
    1069              :          end if
    1070              : 
    1071         1975 :          do k = interp_lo+1, interp_hi-1
    1072         1975 :             if (Vol_new(k+1) >= Vol_new(k) .or. Vol_new(k) >= Vol_new(k-1)) then
    1073              :                if (dbg) write(*,2) 'fix interpolated Vol_new', &
    1074              :                   k, Vol_new(k+1), Vol_new(k), Vol_new(k-1)
    1075            0 :                Vol_min = minval(Vol_new(k-1:k+1))
    1076            0 :                Vol_max = maxval(Vol_new(k-1:k+1))
    1077            0 :                if (Vol_min == Vol_max .or. is_bad(Vol_min) .or. is_bad(Vol_max)) then
    1078            0 :                   ierr = -1
    1079            0 :                   if (s% stop_for_bad_nums) then
    1080            0 :                      write(*,2) 'Vol_min', k, Vol_min
    1081            0 :                      write(*,2) 'Vol_max', k, Vol_max
    1082            0 :                      call mesa_error(__FILE__,__LINE__,'mesh_adjust')
    1083              :                   end if
    1084              :                   if (.not. dbg) return
    1085              :                   write(*,1) 'Vol_min', Vol_min
    1086              :                   write(*,1) 'Vol_max', Vol_max
    1087              :                   call mesa_error(__FILE__,__LINE__,'debug: mesh_adjust')
    1088              :                end if
    1089            0 :                Vm1 = Vol_new(k-1)
    1090            0 :                V00 = Vol_new(k)
    1091            0 :                Vp1 = Vol_new(k+1)
    1092            0 :                Vol_new(k-1) = Vol_max
    1093            0 :                Vol_new(k) = (Vol_max + Vol_min)/2
    1094            0 :                Vol_new(k+1) = Vol_min
    1095              :                if (dbg) write(*,2) 'new Vol_new',  &
    1096              :                   k, Vol_new(k+1), Vol_new(k), Vol_new(k-1)
    1097            0 :                if (Vol_new(k+1) >= Vol_new(k) .or. Vol_new(k) >= Vol_new(k-1)) then
    1098            0 :                   ierr = -1
    1099            0 :                   if (.not. dbg) return
    1100              :                   write(*,1) 'Vol_new(k-1)', Vol_new(k-1)
    1101              :                   write(*,1) 'Vol_new(k)', Vol_new(k)
    1102              :                   write(*,1) 'Vol_new(k+1)', Vol_new(k+1)
    1103              :                   call mesa_error(__FILE__,__LINE__,'debug: do_lnR_and_lnd in mesh adjust: interpolation gave non-pos volume')
    1104              :                end if
    1105              :             end if
    1106              :          end do
    1107              : 
    1108           10 :          call set1_new_r(nzlo)
    1109         1975 :          do k = nzlo, min(nzhi,nz-1)
    1110         1965 :             if (ierr /= 0) cycle
    1111              : 
    1112         1965 :             call set1_new_r(k+1)
    1113              : 
    1114         1965 :             if (cell_type(k) == unchanged_type) then
    1115          493 :                call store_lnd_in_xh(s, k, lnd_old(comes_from(k)), xh)
    1116          493 :                density_new(k) = old_rho(comes_from(k))
    1117          493 :                cycle
    1118              :             end if
    1119              : 
    1120         1472 :             if (new_r(k) <= new_r(k+1)) then
    1121              :                if (dbg) then
    1122              :                   write(*,*) 'do_lnR_and_lnd: (new_r(k) <= new_r(k+1))'
    1123              :                   stop
    1124              :                end if
    1125            0 :                ierr = -1; cycle
    1126              :             end if
    1127              : 
    1128         1472 :             cell_Vol = Vol_new(k)-Vol_new(k+1)
    1129         1472 :             if (cell_Vol <= 0) then
    1130              :                if (dbg) then
    1131              :                   write(*,2) 'do_lnR_and_lnd: cell_Vol <= 0', k
    1132              :                end if
    1133            0 :                ierr = -1; cycle
    1134              :             end if
    1135         1472 :             if (dq(k) <= 0) then
    1136              :                if (dbg) then
    1137              :                   write(*,2) 'do_lnR_and_lnd: dq(k) <= 0', k
    1138              :                end if
    1139            0 :                ierr = -1; cycle
    1140              :             end if
    1141         1472 :             density_new(k) = xmstar*dq(k)/cell_Vol
    1142         1482 :             call store_rho_in_xh(s, k, density_new(k), xh)
    1143              : 
    1144              :          end do
    1145              : 
    1146           10 :          if (ierr /= 0) then
    1147              :             if (.not. dbg) return
    1148              :             call mesa_error(__FILE__,__LINE__,'debug: failed in mesh adjust do_lnR_and_lnd')
    1149              :          end if
    1150              : 
    1151           10 :          n = nzlo - 1
    1152           10 :          if (n > 0) then
    1153         8430 :             do k=1,n
    1154         8420 :                new_r(k) = old_r(k)
    1155         8420 :                density_new(k) = old_rho(k)
    1156         8430 :                Vol_new(k) = four_thirds_pi*new_r(k)*new_r(k)*new_r(k)
    1157              :             end do
    1158              :          end if
    1159              : 
    1160           10 :          if (nzhi < nz) then
    1161            4 :             n = nz - nzhi - 1  ! nz-n = nzhi+1
    1162          236 :             do k=0,n
    1163          232 :                new_r(nz-k) = old_r(nz_old-k)
    1164          232 :                density_new(nz-k) = old_rho(nz_old-k)
    1165          236 :                Vol_new(nz-k) = four_thirds_pi*new_r(nz-k)*new_r(nz-k)*new_r(nz-k)
    1166              :             end do
    1167              :          else  ! nzhi == nz
    1168            6 :             density_new(nz) = xmstar*dq(nz)/(Vol_new(nz) - Vol_center)
    1169            6 :             new_r(nz) = pow(Vol_new(nz)/four_thirds_pi, one_third)
    1170              : 
    1171              :             if (dbg) then
    1172              :                write(*,2) 'old_rho(nz_old)', nz_old, old_rho(nz_old)
    1173              :                write(*,2) 'density_new(nz)', nz, density_new(nz)
    1174              :             end if
    1175              : 
    1176              :          end if
    1177              : 
    1178        10633 :          do k=1,nz
    1179        10623 :             Vol_init(k) = Vol_new(k)
    1180        10633 :             density_init(k) = density_new(k)
    1181              :          end do
    1182              : 
    1183        10633 :          do k=1,nz
    1184        10623 :             from_k = comes_from(k)
    1185        10623 :             if (new_r(k) == old_r(from_k)) then
    1186         9189 :                xh(s%i_lnR,k) = xh_old(s%i_lnR,from_k)
    1187              :             else
    1188         1434 :                call store_r_in_xh(s,k,new_r(k),xh)
    1189              :             end if
    1190        10633 :             if (density_new(k) == old_rho(from_k)) then
    1191         9145 :                xh(s%i_lnd,k) = xh_old(s%i_lnd,from_k)
    1192              :             else
    1193         1478 :                call store_rho_in_xh(s,k,density_new(k),xh)
    1194              :             end if
    1195              :          end do
    1196              : 
    1197              : 
    1198              :          contains
    1199              : 
    1200         1975 :          subroutine set1_new_r(k)
    1201              :             integer, intent(in) :: k
    1202              :             include 'formats'
    1203         1975 :             if (cell_type(k) == unchanged_type) then
    1204          503 :                new_r(k) = old_r(comes_from(k))
    1205              :             else
    1206         1472 :                new_r(k) = pow(Vol_new(k)/four_thirds_pi, one_third)
    1207              :             end if
    1208         1975 :          end subroutine set1_new_r
    1209              : 
    1210              : 
    1211              :       end subroutine do_lnR_and_lnd
    1212              : 
    1213              : 
    1214        10623 :       subroutine do_xa( &
    1215        10623 :             s, nz, nz_old, k, species, cell_type, comes_from, &
    1216        10623 :             xa, xa_old, xa_c0, xa_c1, xa_c2, &
    1217              :             xq, dq, xq_old,  dq_old, mesh_adjust_use_quadratic, ierr)
    1218              :          use chem_def, only: chem_isos
    1219              :          type (star_info), pointer :: s
    1220              :          integer, intent(in) :: nz, nz_old, species, k, cell_type(:), comes_from(:)
    1221              :          real(dp), dimension(:,:), pointer :: xa, xa_old
    1222              :          real(dp), dimension(:,:) :: xa_c0, xa_c1, xa_c2
    1223              :          real(dp), dimension(:), pointer :: xq, dq, xq_old, dq_old
    1224              :          logical, intent(in) :: mesh_adjust_use_quadratic
    1225              :          integer, intent(out) :: ierr
    1226              : 
    1227              :          integer :: j, jj, k_old, k_old_last, kdbg, order
    1228        10623 :          real(dp) :: xq_outer, cell_dq, xa_sum, total(species)
    1229              :          logical :: dbg_get_integral
    1230              : 
    1231              :          include 'formats'
    1232              : 
    1233        10623 :          ierr = 0
    1234              : 
    1235        10623 :          kdbg = -1074
    1236              : 
    1237        10623 :          if (mesh_adjust_use_quadratic) then
    1238        10623 :             order = 2
    1239              :          else
    1240            0 :             order = 1
    1241              :          end if
    1242              : 
    1243        10623 :          if (cell_type(k) == unchanged_type .or. &
    1244              :                cell_type(k) == revised_type) then
    1245        82359 :             do j=1,species
    1246        82359 :                xa(j,k) = xa_old(j,comes_from(k))
    1247              :             end do
    1248              :             return
    1249              :          end if
    1250              : 
    1251         1472 :          xq_outer = xq(k)
    1252         1472 :          if (k == nz) then
    1253            0 :             cell_dq = 1 - xq_outer
    1254              :          else
    1255         1472 :             cell_dq = dq(k)
    1256              :          end if
    1257              : 
    1258         1472 :          k_old = max(comes_from(k)-1,1)
    1259              : 
    1260              :          ! sum the old abundances between xq_outer and xq_inner
    1261              :          dbg_get_integral = .false.
    1262        13248 :          total(:) = 0
    1263        13248 :          do j=1,species
    1264        11776 :             dbg_get_integral = (k == kdbg) .and. (j == 1)  ! h1
    1265        11776 :             if (dbg_get_integral) write(*,2) trim(chem_isos% name(s% chem_id(j)))
    1266              :             call get_xq_integral( &
    1267              :                k_old, nz_old, xq_old, xq_outer, cell_dq, &
    1268              :                order, xa_c0(:,j), xa_c1(:,j), xa_c2(:,j), &
    1269        13248 :                total(j), dbg_get_integral, k_old_last, ierr)
    1270              :          end do
    1271              : 
    1272        13248 :          xa(:,k) = total(:)/cell_dq
    1273              : 
    1274         1472 :          if (k == kdbg) then
    1275            0 :             do j=1,species
    1276            0 :                write(*,2) 'new ' // trim(chem_isos% name(s% chem_id(j))), k, xa(j,k)
    1277              :             end do
    1278              :          end if
    1279              : 
    1280        13248 :          do j=1,species
    1281        13248 :             if (xa(j,k) > 1 + 1d-8 .or. xa(j,k) < -1d-8) then
    1282            0 :                ierr = -1
    1283            0 :                return
    1284              : 
    1285              :                do jj=1,species
    1286              :                   write(*,1) 'xa ' // trim(chem_isos% name(s% chem_id(jj))), xa(jj,k)
    1287              :                end do
    1288              :                write(*,'(A)')
    1289              :                write(*,2) 'sum xa', k, sum(xa(:,k))
    1290              :                write(*,'(A)')
    1291              :                write(*,2) 'xa ' // trim(chem_isos% name(s% chem_id(j))), k, xa(j,k)
    1292              :                write(*,'(A)')
    1293              :                write(*,2) 'xq_outer', k, xq_outer
    1294              :                write(*,2) 'xq_inner', k, xq_outer + cell_dq
    1295              :                write(*,2) 'cell_dq', k, cell_dq
    1296              :                write(*,'(A)')
    1297              :                write(*,2) 'xq_old(k_old)', k_old, xq_old(k_old)
    1298              :                write(*,2) 'xq_inner(k_old)', k_old, xq_old(k_old)+dq_old(k_old)
    1299              :                write(*,2) 'dq_old(k_old)', k_old, dq_old(k_old)
    1300              :                write(*,'(A)')
    1301              :                write(*,2) 'xa_c0(k_old,j)', k_old, xa_c0(k_old,j)
    1302              :                write(*,2) 'xa_c1(k_old,j)', k_old, xa_c1(k_old,j)
    1303              :                write(*,2) 'xa_c2(k_old,j)', k_old, xa_c2(k_old,j)
    1304              :                write(*,'(A)')
    1305              :                write(*,2) 'old outer', k_old, xa_c0(k_old,j) + xa_c1(k_old,j)*dq_old(k_old)/2
    1306              :                write(*,2) 'old inner', k_old, xa_c0(k_old,j) - xa_c1(k_old,j)*dq_old(k_old)/2
    1307              :                write(*,'(A)')
    1308              :                call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do_xa')
    1309              :             end if
    1310              :          end do
    1311              : 
    1312        13248 :          xa_sum = sum(xa(:,k))
    1313              :          !write(*,1) 'xa_sum', xa_sum
    1314              : 
    1315         1472 :          if (is_bad(xa_sum)) then
    1316            0 :             ierr = -1
    1317            0 :             if (s% stop_for_bad_nums) then
    1318            0 :                write(*,2) 'xa_sum', k, xa_sum
    1319            0 :                call mesa_error(__FILE__,__LINE__,'mesh adjust: do_xa')
    1320              :             end if
    1321              :             return
    1322              : 
    1323              :             write(*,*) 'xa_sum', xa_sum
    1324              :             write(*,*) 'bug in revise mesh, do_xa bad num: k', k
    1325              :             call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do_xa')
    1326              :          end if
    1327              : 
    1328         1472 :          if (abs(1-xa_sum) > 1d-3) then
    1329            0 :             ierr = -1
    1330            0 :             return
    1331              :          end if
    1332              : 
    1333        13248 :          xa(:,k) = xa(:,k) / xa_sum
    1334              : 
    1335              :       end subroutine do_xa
    1336              : 
    1337              : 
    1338        10623 :       subroutine do1_lnT( &
    1339              :             s, nz_old, k, &
    1340        10623 :             species, cell_type, comes_from, &
    1341              :             xa, xh, xh_old, &
    1342        10623 :             xq, dq, xq_old, dq_old, eta_old, energy_old, lnT_old, &
    1343        10623 :             specific_PE_old, specific_KE_old, w_old, &
    1344        21246 :             density_new, energy_new, ierr)
    1345              :          use eos_def
    1346              :          use star_utils, only: set_rmid, cell_specific_PE, cell_specific_KE
    1347              :          type (star_info), pointer :: s
    1348              :          integer, intent(in) :: nz_old, k, species, cell_type(:), comes_from(:)
    1349              :          real(dp), dimension(:,:), pointer :: xa, xh, xh_old
    1350              :          real(dp), dimension(:) :: &
    1351              :             xq, dq, xq_old, dq_old, eta_old, energy_old, lnT_old, &
    1352              :             specific_PE_old, specific_KE_old, w_old, density_new, energy_new
    1353              :          integer, intent(out) :: ierr
    1354              : 
    1355              :          integer :: k_old
    1356              :          real(dp) :: &
    1357              :             Rho, logRho, xq_outer, cell_dq, avg_energy, avg_PE, avg_KE, &
    1358              :             new_PE, new_KE, max_delta_energy, delta_energy, revised_energy, &
    1359        10623 :             sum_lnT, avg_lnT, new_lnT, sum_energy, new_xa(species), &
    1360              :             d_dlnR00, d_dlnRp1, d_dv00, d_dvp1
    1361              : 
    1362              :          include 'formats'
    1363              : 
    1364        10623 :          ierr = 0
    1365        95607 :          new_xa(:) = xa(:,k)
    1366        10623 :          k_old = comes_from(k)
    1367              : 
    1368        10623 :          if (cell_type(k) == unchanged_type) then
    1369         9151 :             xh(s%i_lnT, k) = xh_old(s%i_lnT, k_old)
    1370         9151 :             energy_new(k) = energy_old(k_old)
    1371         9151 :             if (is_bad(energy_old(k_old))) then
    1372            0 :                write(*,2) 'energy_old(k_old)', k_old, energy_old(k_old)
    1373            0 :                call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do1_lnT')
    1374              :             end if
    1375              :             return
    1376              :          end if
    1377              : 
    1378         1472 :          xq_outer = xq(k)
    1379         1472 :          cell_dq = dq(k)
    1380              : 
    1381         1472 :          if (cell_type(k) == revised_type) then
    1382            0 :             avg_lnT = get_lnT_from_xh(s, k, xh_old)
    1383              :          else  ! find average lnT between xq_outer and xq_inner
    1384              :             call get_old_value_integral( &
    1385              :                k, k_old, nz_old, xq_old, dq_old, xq_outer, cell_dq, &
    1386         1472 :                lnT_old, sum_lnT, dbg, ierr)
    1387         1472 :             if (ierr /= 0) then
    1388              :                if (dbg) write(*,*) 'get_old_value_integral lnT failed for do1_lnT'
    1389              :                if (.not. dbg) return
    1390              :                call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do1_lnT')
    1391              :             end if
    1392         1472 :             avg_lnT = sum_lnT/cell_dq
    1393              :          end if
    1394              : 
    1395         1472 :          if (is_bad(avg_lnT) .or. avg_lnT < 0 .or. avg_lnT > 100) then
    1396            0 :             ierr = -1
    1397            0 :             if (s% stop_for_bad_nums) then
    1398            0 :                write(*,2) 'avg_lnT', k, avg_lnT
    1399            0 :                call mesa_error(__FILE__,__LINE__,'mesh adjust: do1_lnT')
    1400              :             end if
    1401              :             return
    1402              :          end if
    1403              : 
    1404         1472 :          if (.not. s% mesh_adjust_get_T_from_E) then
    1405            0 :             call store_lnT_in_xh(s, k, avg_lnT, xh)
    1406            0 :             energy_new(k) = energy_old(k_old)
    1407            0 :             if (is_bad(energy_old(k_old))) then
    1408            0 :                write(*,2) 'energy_old(k_old)', k_old, energy_old(k_old)
    1409            0 :                call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do1_lnT')
    1410              :             end if
    1411              :             return
    1412              :          end if
    1413              : 
    1414         1472 :          if (eta_old(k_old) >= eta_limit) then
    1415            0 :             call store_lnT_in_xh(s, k, avg_lnT, xh)
    1416            0 :             energy_new(k) = energy_old(k_old)
    1417            0 :             if (is_bad(energy_old(k_old))) then
    1418            0 :                write(*,2) 'eta_old(k_old)', k_old, eta_old(k_old)
    1419            0 :                write(*,2) 'energy_old(k_old)', k_old, energy_old(k_old)
    1420            0 :                call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do1_lnT')
    1421              :             end if
    1422              :             return
    1423              :          end if
    1424              : 
    1425              :          if (dbg) write(*,2) 'eta_old(k_old)', k_old, eta_old(k_old)
    1426              : 
    1427         1472 :          if (cell_type(k) == revised_type) then
    1428            0 :             avg_energy = energy_old(k_old)
    1429              :          else  ! find average internal energy between q_outer and q_inner
    1430              :             call get_old_value_integral( &
    1431              :                k, k_old, nz_old, xq_old, dq_old, xq_outer, cell_dq, &
    1432         1472 :                energy_old, sum_energy, dbg, ierr)
    1433         1472 :             if (ierr /= 0) then
    1434              :                if (dbg) write(*,*) 'get_old_value_integral failed for do1_lnT'
    1435              :                if (.not. dbg) return
    1436              :                call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: energy_old do1_lnT')
    1437              :             end if
    1438         1472 :             avg_energy = sum_energy/cell_dq
    1439              :          end if
    1440              : 
    1441         1472 :          if (s% max_rel_delta_IE_for_mesh_total_energy_balance == 0d0) then
    1442              : 
    1443            0 :             energy_new(k) = avg_energy
    1444              : 
    1445              :          else
    1446              : 
    1447         1472 :             if (cell_type(k) == revised_type) then
    1448            0 :                avg_PE = specific_PE_old(k_old)
    1449              :             else  ! find average potential energy between q_outer and q_inner
    1450              :                call get_old_value_integral( &
    1451              :                   k, k_old, nz_old, xq_old, dq_old, xq_outer, cell_dq, &
    1452         1472 :                   specific_PE_old, sum_energy, dbg, ierr)
    1453         1472 :                if (ierr /= 0) then
    1454              :                   if (dbg) write(*,*) 'get_old_value_integral failed for do1_lnT'
    1455              :                   if (.not. dbg) return
    1456              :                   call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: specific_PE_old do1_lnT')
    1457              :                end if
    1458         1472 :                avg_PE = sum_energy/cell_dq
    1459              :             end if
    1460              : 
    1461         1472 :             if (cell_type(k) == revised_type) then
    1462            0 :                avg_KE = specific_KE_old(k_old)
    1463              :             else  ! find average kinetic energy between q_outer and q_inner
    1464              :                call get_old_value_integral( &
    1465              :                   k, k_old, nz_old, xq_old, dq_old, xq_outer, cell_dq, &
    1466         1472 :                   specific_KE_old, sum_energy, dbg, ierr)
    1467         1472 :                if (ierr /= 0) then
    1468              :                   if (dbg) write(*,*) 'get_old_value_integral failed for do1_lnT'
    1469              :                   if (.not. dbg) return
    1470              :                   call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: specific_KE_old do1_lnT')
    1471              :                end if
    1472         1472 :                avg_KE = sum_energy/cell_dq
    1473              :             end if
    1474              : 
    1475         1472 :             if (ierr /= 0) return
    1476         1472 :             new_PE = cell_specific_PE(s,k,d_dlnR00,d_dlnRp1)
    1477         1472 :             if (s% u_flag) then
    1478            0 :                s% u(k) = s% xh(s% i_u,k)
    1479         1472 :             else if (s% v_flag) then
    1480            0 :                s% v(k) = s% xh(s% i_v,k)
    1481            0 :                if (k < s% nz) s% v(k+1) = s% xh(s% i_v,k+1)
    1482              :             end if
    1483         1472 :             new_KE = cell_specific_KE(s,k,d_dv00,d_dvp1)
    1484              : 
    1485         1472 :             max_delta_energy = avg_energy*s% max_rel_delta_IE_for_mesh_total_energy_balance
    1486         1472 :             delta_energy = avg_PE + avg_KE - (new_PE + new_KE)
    1487         1472 :             if (abs(delta_energy) > max_delta_energy) then
    1488            0 :                delta_energy = sign(max_delta_energy,delta_energy)
    1489              :             end if
    1490         1472 :             energy_new(k) = avg_energy + delta_energy
    1491              : 
    1492         1472 :             if (energy_new(k) <= 0d0) then
    1493            0 :                write(*,2) 'energy_new(k) <= 0d0', k, energy_new(k), avg_energy
    1494            0 :                energy_new(k) = avg_energy
    1495              :             end if
    1496              : 
    1497              :          end if
    1498              : 
    1499              :          ! call eos to calculate lnT from new internal energy
    1500              : 
    1501         1472 :          Rho = density_new(k)
    1502         1472 :          logRho = log10(Rho)
    1503              :          call set_lnT_for_energy( &
    1504              :             s, k, &
    1505              :             s% net_iso(ih1), s% net_iso(ihe3), s% net_iso(ihe4), species, new_xa, &
    1506         1472 :             Rho, logRho, energy_new(k), avg_lnT, new_lnT, revised_energy, ierr)
    1507         1472 :          if (ierr /= 0) then
    1508              :             if (dbg) write(*,*) 'set_lnT_for_energy failed', k
    1509            0 :             new_lnT = avg_lnT
    1510            0 :             energy_new(k) = energy_old(k_old)
    1511            0 :             ierr = 0
    1512              :          end if
    1513              : 
    1514         1472 :          call store_lnT_in_xh(s, k, new_lnT, xh)
    1515              : 
    1516         1472 :          if (ierr /= 0) then
    1517            0 :             write(*,2) 'mesh_adjust do1_lnT ierr', ierr
    1518            0 :             call mesa_error(__FILE__,__LINE__,'do1_lnT')
    1519              :          end if
    1520              : 
    1521              :       end subroutine do1_lnT
    1522              : 
    1523              : 
    1524         5888 :       subroutine get_old_value_integral( &
    1525         5888 :             k_new, k_old_in, nz_old, xq_old, dq_old, xq_outer, dq_range, &
    1526         5888 :             value_old, integral, dbg, ierr)
    1527              :          integer, intent(in) :: k_new, k_old_in, nz_old
    1528              :          real(dp), intent(in) :: xq_old(:), dq_old(:), xq_outer, dq_range
    1529              :          real(dp), intent(in), dimension(:) :: value_old
    1530              :          real(dp), intent(out) :: integral
    1531              :          logical, intent(in) :: dbg
    1532              :          integer, intent(out) :: ierr
    1533              :          real(dp), pointer :: p(:,:)
    1534              :          nullify(p)
    1535              :          call get_old_integral( &
    1536              :             k_new, k_old_in, nz_old, xq_old, dq_old, xq_outer, dq_range, &
    1537         5888 :             value_old, p, integral, dbg, ierr)
    1538         5888 :       end subroutine get_old_value_integral
    1539              : 
    1540              : 
    1541         5888 :       subroutine get_old_integral( &
    1542         5888 :             k_new, k_old_in, nz_old, xq_old, dq_old, xq_outer, dq_range, &
    1543         5888 :             value_old, xh_old, integral, dbg, ierr)
    1544              :          integer, intent(in) :: k_new, k_old_in, nz_old
    1545              :          real(dp), intent(in) :: xq_old(:), dq_old(:), xq_outer, dq_range
    1546              :          real(dp), intent(in) :: value_old(:)
    1547              :          real(dp), intent(in), pointer :: xh_old(:,:)
    1548              :          real(dp), intent(out) :: integral
    1549              :          logical, intent(in) :: dbg
    1550              :          integer, intent(out) :: ierr
    1551              : 
    1552              :          integer :: k, k_old
    1553              :          real(dp) :: xq_inner, sum_dqs, old_xq_outer, old_xq_inner, &
    1554              :             dq_overlap, val
    1555              : 
    1556              :          include 'formats'
    1557              : 
    1558         5888 :          if (dbg) write(*,*)
    1559              : 
    1560         5888 :          ierr = 0
    1561              : 
    1562         5888 :          k_old = k_old_in
    1563              :          ! move starting k_old if necessary
    1564            0 :          do
    1565         5888 :             if (k_old <= 1) exit
    1566         5888 :             if (xq_old(k_old) <= xq_outer) exit
    1567         5888 :             k_old = k_old - 1
    1568              :          end do
    1569              : 
    1570         5888 :          xq_inner = xq_outer + dq_range
    1571         5888 :          old_xq_inner = xq_old(k_old)
    1572         5888 :          sum_dqs = 0
    1573         5888 :          integral = 0d0
    1574              : 
    1575         5888 :          if (dbg) write(*,*)
    1576         5888 :          if (dbg) write(*,3) 'k_new k_old xq_outer xq_inner dq_range', &
    1577            0 :             k_new, k_old, xq_outer, xq_inner, dq_range
    1578              : 
    1579        17664 :          do k = k_old, nz_old
    1580              : 
    1581        17664 :             if (dq_range <= sum_dqs) exit
    1582        11776 :             old_xq_outer = old_xq_inner
    1583        11776 :             if (k == nz_old) then
    1584            0 :                old_xq_inner = 1
    1585              :             else
    1586        11776 :                old_xq_inner = xq_old(k+1)
    1587              :             end if
    1588              : 
    1589        11776 :             if (dbg) write(*,3) 'k_new k_old old_xq_outer old_xq_inner', &
    1590            0 :                k_new, k, old_xq_outer, old_xq_inner
    1591              : 
    1592        11776 :             val = value_old(k)
    1593              : 
    1594        17664 :             if (old_xq_inner <= xq_inner .and. old_xq_outer >= xq_outer) then
    1595              : 
    1596        11776 :                if (dbg) write(*,1) 'entire old cell is in new range'
    1597              : 
    1598        11776 :                sum_dqs = sum_dqs + dq_old(k)
    1599        11776 :                integral = integral + val*dq_old(k)
    1600              : 
    1601            0 :             else if (old_xq_inner >= xq_inner .and. old_xq_outer <= xq_outer) then
    1602              : 
    1603            0 :                if (dbg) write(*,1) 'entire new range is in this old cell'
    1604              : 
    1605            0 :                sum_dqs = dq_range
    1606            0 :                integral = val*dq_range
    1607              : 
    1608              :             else  ! only use the part of old cell that is in new range
    1609              : 
    1610            0 :                if (xq_inner <= old_xq_inner) then
    1611              : 
    1612            0 :                   if (dbg) write(*,1) 'last part of the new range'
    1613              : 
    1614            0 :                   integral = integral + val*(dq_range - sum_dqs)
    1615            0 :                   sum_dqs = dq_range
    1616              : 
    1617              :                else  ! partial overlap -- general case
    1618              : 
    1619            0 :                   dq_overlap = max(0d0, old_xq_inner - xq_outer)
    1620            0 :                   sum_dqs = sum_dqs + dq_overlap
    1621            0 :                   integral = integral + val*dq_overlap
    1622              : 
    1623            0 :                   if (dbg) write(*,1) 'partial overlap'
    1624              : 
    1625              :                end if
    1626              : 
    1627              :             end if
    1628              : 
    1629              :          end do
    1630              : 
    1631         5888 :          if (dbg) write(*,2) 'integral/dq_range', &
    1632            0 :             k_new, integral/dq_range, integral, dq_range
    1633         5888 :          if (dbg) write(*,*)
    1634              : 
    1635         5888 :       end subroutine get_old_integral
    1636              : 
    1637              : 
    1638         1472 :       subroutine set_lnT_for_energy( &
    1639         1472 :             s, k, h1, he3, he4, species, xa, &
    1640              :             Rho, logRho, energy, lnT_guess, lnT, result_energy, ierr)
    1641              :          type (star_info), pointer :: s
    1642              :          integer, intent(in) :: k, h1, he3, he4, species
    1643              :          real(dp), intent(in) :: xa(species), Rho, logRho, energy, lnT_guess
    1644              :          real(dp), intent(out) :: lnT, result_energy
    1645              :          integer, intent(out) :: ierr
    1646              :          call set_lnT_for_energy_with_tol( &
    1647              :             s, k, h1, he3, he4, species, xa, 1d-11, &
    1648         1472 :             Rho, logRho, energy, lnT_guess, lnT, result_energy, ierr)
    1649         1472 :       end subroutine set_lnT_for_energy
    1650              : 
    1651              : 
    1652         1472 :       subroutine set_lnT_for_energy_with_tol( &
    1653         1472 :             s, k, h1, he3, he4, species, xa, tol, &
    1654              :             Rho, logRho, energy, lnT_guess, lnT, result_energy, ierr)
    1655              :          use eos_support, only: solve_eos_given_DE
    1656              :          use eos_def, only: num_eos_basic_results, num_eos_d_dxa_results, i_lnE
    1657              :          use chem_lib, only: basic_composition_info
    1658              :          type (star_info), pointer :: s
    1659              :          integer, intent(in) :: k, h1, he3, he4, species
    1660              :          real(dp), intent(in) :: xa(species), tol, Rho, logRho, energy, lnT_guess
    1661              :          real(dp), intent(out) :: lnT, result_energy
    1662              :          integer, intent(out) :: ierr
    1663              : 
    1664              :          real(dp) :: &
    1665              :             logT, res(num_eos_basic_results), &
    1666              :             d_dlnd(num_eos_basic_results), d_dlnT(num_eos_basic_results), &
    1667         1472 :             d_dxa(num_eos_d_dxa_results, s% species), &
    1668              :             logT_tol, logE_tol
    1669              : 
    1670              :          include 'formats'
    1671              : 
    1672         1472 :          ierr = 0
    1673              : 
    1674         1472 :          logT_tol = tol  ! 1d-11
    1675         1472 :          logE_tol = tol  ! 1d-11
    1676              :          call solve_eos_given_DE( &
    1677              :             s, k, xa(:), &
    1678              :             logRho, log10(energy), lnT_guess/ln10, &
    1679              :             logT_tol, logE_tol, &
    1680              :             logT, res, d_dlnd, d_dlnT, &
    1681              :             d_dxa, &
    1682         1472 :             ierr)
    1683         1472 :          lnT = logT*ln10
    1684              : 
    1685         1472 :          result_energy = exp(res(i_lnE))
    1686              : 
    1687         1472 :          if (ierr /= 0 .or. is_bad_num(lnT)) then
    1688            0 :             ierr = -1
    1689            0 :             if (s% stop_for_bad_nums) then
    1690            0 :                write(*,2) 'lnT', k, lnT
    1691            0 :                call mesa_error(__FILE__,__LINE__,'mesh adjust: do1_lnT')
    1692              :             end if
    1693              :             return
    1694              :          end if
    1695              : 
    1696              :          contains
    1697              : 
    1698              :          subroutine show
    1699              :             include 'formats'
    1700              :             write(*,'(A)')
    1701              :             write(*,*) 'set_lnT_for_energy ierr', ierr
    1702              :             write(*,*) 'k', k
    1703              :             write(*,'(A)')
    1704              :             write(*,1) 'lnT =', lnT
    1705              :             write(*,'(A)')
    1706              :             write(*,1) 'logRho =', logRho
    1707              :             write(*,1) 'logT_guess =', lnT_guess/ln10
    1708              :             write(*,1) 'energy =', energy
    1709              :             write(*,'(A)')
    1710              :             write(*,'(A)')
    1711              :          end subroutine show
    1712              : 
    1713              :       end subroutine set_lnT_for_energy_with_tol
    1714              : 
    1715              : 
    1716              :       ! Stiriba, Youssef, Appl, Numer. Math. 45, 499-511. 2003.
    1717              : 
    1718              :          ! LPP-HARMOD -- local piecewise parabolic reconstruction
    1719              : 
    1720              :          ! interpolant is derived to conserve integral of v in cell k
    1721              :          ! interpolant slope at cell midpoint is harmonic mean of slopes between adjacent cells
    1722              :          ! where these slopes between cells are defined as the difference between cell averages
    1723              :          ! divided by the distance between cell midpoints.
    1724              :          ! interpolant curvature based on difference between the midpoint slope
    1725              :          ! and the smaller in magnitude of the slopes between adjacent cells.
    1726              : 
    1727              :          ! interpolant f(dq) = a + b*dq + (c/2)*dq^2, with dq = q - q_midpoint
    1728              :          ! c0 holds a's, c1 holds b's, and c2 holds c's.
    1729              : 
    1730              : 
    1731        27576 :       subroutine get1_lpp(k, ldv, nz, j, dq, v, quad, c0, c1, c2)
    1732              :          integer, intent(in) :: k, ldv, nz, j
    1733              :          real(dp), intent(in) :: dq(:)  ! (nz)
    1734              :          real(dp), intent(in) :: v(:,:)  ! (ldv,nz)
    1735              :          logical, intent(in) :: quad
    1736              :          real(dp), dimension(:) :: c0, c1, c2
    1737              : 
    1738              :          real(dp) :: vbdy1, vbdy2, dqhalf, sm1, s00, sprod
    1739              :          real(dp), parameter :: rel_curvature_limit = 0.1d0
    1740              : 
    1741              :          logical :: dbg
    1742              : 
    1743              :          include 'formats'
    1744              : 
    1745        27576 :          if (k == 1 .or. k == nz) then
    1746           48 :             call set_const
    1747           48 :             return
    1748              :          end if
    1749              : 
    1750        27528 :          dbg = .false.
    1751              :          !dbg = (k == 30 .and. j == 3) ! .false.
    1752              : 
    1753        27528 :          sm1 = (v(j,k-1) - v(j,k)) / ((dq(k-1) + dq(k))/2)
    1754        27528 :          s00 = (v(j,k) - v(j,k+1)) / ((dq(k) + dq(k+1))/2)
    1755              : 
    1756        27528 :          sprod = sm1*s00
    1757        27528 :          if (sprod <= 0) then
    1758              :             ! at local min or max, so set slope and curvature to 0.
    1759         8246 :             call set_const
    1760         8246 :             return
    1761              :          end if
    1762              : 
    1763        19282 :          if (.not. quad) then
    1764        19282 :             c0(k) = v(j,k)
    1765        19282 :             c1(k) = (sm1 + s00)/2  ! use average to smooth abundance transitions
    1766        19282 :             c2(k) = 0  ! Yan Wang fixed this -- it was left out initially.
    1767              :          else
    1768            0 :             c1(k) = sprod*2/(s00 + sm1)  ! harmonic mean slope
    1769            0 :             if (abs(sm1) <= abs(s00)) then
    1770            0 :                c2(k) = (sm1 - c1(k))/(2*dq(k))
    1771              :             else
    1772            0 :                c2(k) = (c1(k) - s00)/(2*dq(k))
    1773              :             end if
    1774            0 :             c0(k) = v(j,k) - c2(k)*dq(k)*dq(k)/24
    1775              :          end if
    1776              : 
    1777              :          ! check values at edges for monotonicity
    1778        19282 :          dqhalf = dq(k)/2
    1779        19282 :          vbdy1 = c0(k) + c1(k)*dqhalf + c2(k)/2*dqhalf*dqhalf  ! value at face(k)
    1780        19282 :          vbdy2 = c0(k) - c1(k)*dqhalf + c2(k)/2*dqhalf*dqhalf  ! value at face(k+1)
    1781        19282 :          if ((v(j,k-1) - vbdy1)*(vbdy1 - v(j,k)) < 0 .or. &
    1782              :              (v(j,k) - vbdy2)*(vbdy2 - v(j,k+1)) < 0) then
    1783              :             if (dbg) then
    1784              :                write(*,*) 'non-monotonic'
    1785              :                write(*,2) 'v(j,k-1)', k-1, v(j,k-1)
    1786              :                write(*,2) 'vbdy1', k, vbdy1
    1787              :                write(*,2) 'v(j,k)', k, v(j,k)
    1788              :                write(*,2) 'vbdy2', k, vbdy2
    1789              :                write(*,2) 'v(j,k+1)', k+1, v(j,k+1)
    1790              :                write(*,'(A)')
    1791              :                write(*,2) 'v(j,k-1) - vbdy1', k, v(j,k-1) - vbdy1
    1792              :                write(*,2) 'vbdy1 - v(j,k+1)', k, vbdy1 - v(j,k+1)
    1793              :                write(*,'(A)')
    1794              :                write(*,2) 'v(j,k-1) - vbdy2', k, v(j,k-1) - vbdy2
    1795              :                write(*,2) 'vbdy2 - v(j,k+1)', k, vbdy2 - v(j,k+1)
    1796              :                write(*,'(A)')
    1797              :                write(*,2) 'sm1', k, sm1
    1798              :                write(*,2) 's00', k, s00
    1799              :                write(*,'(A)')
    1800              :                call mesa_error(__FILE__,__LINE__,'debug: get1_lpp')
    1801              :             end if
    1802          167 :             c2(k) = 0
    1803          167 :             if (abs(sm1) <= abs(s00)) then
    1804           84 :                c1(k) = sm1
    1805              :             else
    1806           83 :                c1(k) = s00
    1807              :             end if
    1808              :          end if
    1809              : 
    1810              :          contains
    1811              : 
    1812         8294 :          subroutine set_const
    1813         8294 :             c0(k) = v(j,k)
    1814         8294 :             c1(k) = 0
    1815         8294 :             if (quad) c2(k) = 0
    1816         8294 :          end subroutine set_const
    1817              : 
    1818              :       end subroutine get1_lpp
    1819              : 
    1820              : 
    1821        11776 :       subroutine get_xq_integral( &
    1822        11776 :             k_old_in, nz_old, xq_old, xq_outer, dq, &
    1823        11776 :             order, c0, c1, c2, integral, dbg, k_old_last, ierr)
    1824              :          ! integrate val(j,:) from xq_inner to xq_outer, with xq_inner = xq_outer + dq
    1825              :          integer, intent(in) :: k_old_in, nz_old
    1826              :          real(dp), intent(in) :: xq_old(:), xq_outer, dq
    1827              :          integer, intent(in) :: order  ! 0, 1, 2
    1828              :          real(dp), intent(in), dimension(:) :: c0, c1, c2  ! coefficients
    1829              :          real(dp), intent(out) :: integral
    1830              :          logical, intent(in) :: dbg
    1831              :          integer, intent(out) :: k_old_last, ierr
    1832              : 
    1833              :          integer :: k, k_old
    1834              :          real(dp) :: a, b, c, old_xq_inner, old_xq_outer, xq_inner, &
    1835              :             xq_overlap_outer, xq_overlap_inner, dq1, sum_dqs, old_xq_mid, &
    1836              :             v_overlap_outer, v_overlap_inner, dq_outer, dq_inner, avg_value
    1837              : 
    1838              :          include 'formats'
    1839              : 
    1840        11776 :          if (dbg) write(*,*)
    1841              : 
    1842        11776 :          ierr = 0
    1843        11776 :          k_old = k_old_in
    1844              :          ! move starting k_old if necessary
    1845            0 :          do
    1846        11776 :             if (k_old <= 1) exit
    1847        11776 :             if (xq_old(k_old) <= xq_outer) exit
    1848        11776 :             k_old = k_old - 1
    1849              :          end do
    1850        11776 :          xq_inner = xq_outer + dq
    1851        11776 :          old_xq_inner = xq_old(k_old)
    1852        11776 :          sum_dqs = 0
    1853        11776 :          integral = 0d0
    1854              : 
    1855        35328 :          do k = k_old, nz_old
    1856        35328 :             if (dq <= sum_dqs) exit
    1857        35328 :             old_xq_outer = old_xq_inner
    1858        35328 :             if (k == nz_old) then
    1859            0 :                old_xq_inner = 1
    1860              :             else
    1861        35328 :                old_xq_inner = xq_old(k+1)
    1862              :             end if
    1863        35328 :             xq_overlap_outer = max(xq_outer, old_xq_outer)
    1864        35328 :             xq_overlap_inner = min(xq_inner, old_xq_inner)
    1865              : 
    1866        35328 :             if (dbg) then
    1867            0 :                write(*,2) 'xq_overlap_outer', k, xq_overlap_outer
    1868            0 :                write(*,2) 'xq_outer', k, xq_outer
    1869            0 :                write(*,2) 'old_xq_outer', k, old_xq_outer
    1870            0 :                write(*,2) 'xq_overlap_inner', k, xq_overlap_inner
    1871            0 :                write(*,2) 'xq_inner', k, xq_inner
    1872            0 :                write(*,2) 'old_xq_inner', k, old_xq_inner
    1873              :             end if
    1874              : 
    1875        35328 :             if (sum_dqs == 0 .and. xq_overlap_outer == xq_outer .and.  &
    1876              :                xq_overlap_inner == xq_inner) then
    1877              :                ! fully contained
    1878            0 :                xq_inner = xq_outer + dq
    1879            0 :                xq_overlap_inner = xq_inner
    1880            0 :                dq1 = dq
    1881        35328 :             else if (old_xq_inner >= xq_inner) then  ! this is the last one
    1882        11776 :                dq1 = dq - sum_dqs
    1883              :             else
    1884        23552 :                dq1 = max(0d0, xq_overlap_inner-xq_overlap_outer)
    1885              :             end if
    1886        35328 :             sum_dqs = sum_dqs + dq1
    1887              :             ! interpolant f(dq) = a + b*dq + (c/2)*dq^2, with dq = q - q_midpoint
    1888        35328 :             a = c0(k)
    1889        35328 :             b = c1(k)
    1890        35328 :             if (order == 2) then
    1891        35328 :                c = c2(k)
    1892              :             else
    1893            0 :                c = 0
    1894              :             end if
    1895              : 
    1896        35328 :             if (dq1 == 0 .or. (b==0 .and. c==0)) then
    1897        17233 :                avg_value = a
    1898              :             else
    1899        18095 :                old_xq_mid = (old_xq_outer + old_xq_inner)/2
    1900        18095 :                dq_outer = old_xq_mid - xq_overlap_outer
    1901        18095 :                dq_inner = old_xq_mid - xq_overlap_inner
    1902              : 
    1903        18095 :                if (order == 0) then
    1904            0 :                   avg_value = a
    1905        18095 :                else if (order == 1 .or. c == 0) then
    1906              :                   ! use slope to estimate average value in the region being used
    1907        18095 :                   if (dbg) write(*,*) 'use slope to estimate average value'
    1908        18095 :                   v_overlap_outer = a + dq_outer*b
    1909        18095 :                   v_overlap_inner = a + dq_inner*b
    1910        18095 :                   avg_value = (v_overlap_outer + v_overlap_inner)/2
    1911              :                else  ! use quadratic reconstruction
    1912            0 :                   if (dbg) write(*,*) 'use quadratic reconstruction'
    1913              :                   avg_value = &
    1914              :                      a + b*(dq_inner + dq_outer)/2 + &
    1915            0 :                         c*(dq_inner*dq_inner + dq_inner*dq_outer + dq_outer*dq_outer)/6
    1916              :                end if
    1917              :             end if
    1918        35328 :             integral = integral + dq1*avg_value
    1919        35328 :             if (dbg) then
    1920            0 :                write(*,2) 'a', k, a
    1921            0 :                write(*,2) 'b', k, b
    1922            0 :                write(*,2) 'c', k, c
    1923            0 :                write(*,2) 'dq1', k, dq1
    1924            0 :                write(*,2) 'avg_value', k, avg_value
    1925            0 :                write(*,2) 'integral', k, integral
    1926            0 :                write(*,'(A)')
    1927              :             end if
    1928        35328 :             k_old_last = k
    1929        35328 :             if (old_xq_inner >= xq_inner) exit  ! this is the last one
    1930              : 
    1931              :          end do
    1932              : 
    1933        11776 :          if (dbg) write(*,1) 'integral/dq', integral/dq, integral, dq
    1934              : 
    1935        11776 :       end subroutine get_xq_integral
    1936              : 
    1937              : 
    1938            0 :       subroutine adjust_omega(s, nz, nz_old, nzlo, nzhi, old_j_rot, &
    1939            0 :             old_dq, new_dq, old_dqbar, new_dqbar, ierr)
    1940              :          use hydro_rotation, only: w_div_w_roche_jrot, update1_i_rot_from_xh
    1941              :          use const_def, only: qp
    1942              :          use accurate_sum, only: accurate_real, assignment(=), operator(+), operator(-)
    1943              :          type (star_info), pointer :: s
    1944              :          integer, intent(in) :: nz, nz_old, nzlo, nzhi
    1945              :          real(dp), dimension(:), intent(in) :: &
    1946              :             old_j_rot, old_dq, new_dq, old_dqbar, new_dqbar
    1947              :          integer, intent(out) :: ierr
    1948              :          type(accurate_real) :: j_error
    1949              :          real(dp) :: correction_norm, domega, r00
    1950              :          integer :: k
    1951              : 
    1952            0 :          ierr = 0
    1953              : 
    1954            0 : !$OMP PARALLEL DO PRIVATE(k, r00) SCHEDULE(dynamic,2)
    1955              :          do k = 1, nz
    1956              :             r00 = get_r_from_xh(s,k)
    1957              :             s% w_div_w_crit_roche(k) = &
    1958              :                w_div_w_roche_jrot(r00,s% m(k),s% j_rot(k),s% cgrav(k), &
    1959              :                s% w_div_wcrit_max, s% w_div_wcrit_max2, s% w_div_wc_flag)
    1960              :             call update1_i_rot_from_xh(s, k)
    1961              :             s% omega(k) = s% j_rot(k)/s% i_rot(k)% val
    1962              :          end do
    1963              : !$OMP END PARALLEL DO
    1964              : 
    1965              :          ! Accumulate old minus new in one sum to avoid subtracting rounded totals.
    1966            0 :          j_error = 0.0_qp
    1967            0 :          do k = 1, nz_old
    1968            0 :             j_error = j_error + real(old_dqbar(k),qp)*real(old_j_rot(k),qp)
    1969              :          end do
    1970            0 :          do k = 1, nz
    1971            0 :             j_error = j_error - real(new_dqbar(k),qp)*real(s% j_rot(k),qp)
    1972              :          end do
    1973            0 :          correction_norm = 0d0
    1974            0 :          do k = nzlo, nzhi
    1975              :             correction_norm = correction_norm + &
    1976            0 :                new_dqbar(k)*s% i_rot(k)% val
    1977              :          end do
    1978              : 
    1979              :          ! RSP uses half of the innermost cell in its dm_bar definition.
    1980            0 :          if (s% rsp_flag .or. s% RSP2_flag) then
    1981              :             j_error = j_error - &
    1982            0 :                0.5_qp*real(old_dq(nz_old),qp)*real(old_j_rot(nz_old),qp)
    1983              :             j_error = j_error + &
    1984            0 :                0.5_qp*real(new_dq(nz),qp)*real(s% j_rot(nz),qp)
    1985            0 :             if (nzhi == nz) correction_norm = correction_norm - &
    1986            0 :                0.5d0*new_dq(nz)*s% i_rot(nz)% val
    1987              :          end if
    1988              : 
    1989            0 :          if (correction_norm <= 0d0 .or. is_bad(correction_norm)) then
    1990            0 :             ierr = -1
    1991            0 :             return
    1992              :          end if
    1993            0 :          domega = real(j_error%value()/real(correction_norm,qp),dp)
    1994            0 :          if (is_bad(domega)) then
    1995            0 :             ierr = -1
    1996            0 :             return
    1997              :          end if
    1998              : 
    1999              :          ! A constant omega correction restores the discrete total angular momentum.
    2000            0 : !$OMP PARALLEL DO PRIVATE(k, r00) SCHEDULE(dynamic,2)
    2001              :          do k = nzlo, nzhi
    2002              :             s% j_rot(k) = s% j_rot(k) + domega*s% i_rot(k)% val
    2003              :             r00 = get_r_from_xh(s,k)
    2004              :             s% w_div_w_crit_roche(k) = &
    2005              :                w_div_w_roche_jrot(r00,s% m(k),s% j_rot(k),s% cgrav(k), &
    2006              :                s% w_div_wcrit_max, s% w_div_wcrit_max2, s% w_div_wc_flag)
    2007              :             call update1_i_rot_from_xh(s, k)
    2008              :             s% omega(k) = s% j_rot(k)/s% i_rot(k)% val
    2009              :          end do
    2010              : !$OMP END PARALLEL DO
    2011              : 
    2012              :       end subroutine adjust_omega
    2013              : 
    2014              : 
    2015              :       ! like adjust_omega.  conserve kinetic energy
    2016            0 :       subroutine do_v( &
    2017            0 :             s, nz, nz_old, cell_type, comes_from, &
    2018            0 :             old_xq, new_xq, old_dq, new_dq, xh, xh_old, &
    2019            0 :             xout_old, xout_new, old_dqbar, new_dqbar, old_ke, ierr)
    2020              :          use alloc
    2021              :          type (star_info), pointer :: s
    2022              :          integer, intent(in) :: nz, nz_old
    2023              :          integer, dimension(:) :: cell_type, comes_from
    2024              :          real(dp), dimension(:) :: &
    2025              :             xout_old, xout_new, old_dqbar, new_dqbar, &
    2026              :             old_xq, new_xq, old_dq, new_dq, old_ke
    2027              :          real(dp), dimension(:,:) :: xh, xh_old
    2028              :          integer, intent(out) :: ierr
    2029              : 
    2030              :          integer :: k, op_err, i_v
    2031              :          real(dp) :: old_ke_tot, new_ke_tot, xmstar, err
    2032              : 
    2033              :          include 'formats'
    2034            0 :          ierr = 0
    2035            0 :          i_v = s% i_v
    2036            0 :          xmstar = s% xmstar
    2037              : 
    2038            0 :          old_ke_tot = 0d0
    2039            0 :          do k=1,nz_old  ! skip common factor 1/2 xmstar in ke
    2040            0 :             old_ke(k) = old_dqbar(k)*xh_old(i_v,k)*xh_old(i_v,k)
    2041            0 :             old_ke_tot = old_ke_tot + old_ke(k)
    2042              :          end do
    2043              : 
    2044            0 : !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
    2045              :          do k = 1, nz
    2046              :             op_err = 0
    2047              :             call adjust1_v( &
    2048              :                s, k, nz, nz_old, cell_type, comes_from, xout_old, xout_new, &
    2049              :                old_dqbar, new_dqbar, old_ke, i_v, xh, xh_old, op_err)
    2050              :             if (op_err /= 0) ierr = op_err
    2051              :          end do
    2052              : !$OMP END PARALLEL DO
    2053            0 :          if (ierr /= 0) then
    2054            0 :             return
    2055              :          end if
    2056              : 
    2057            0 :          new_ke_tot = 0
    2058            0 :          do k=1,nz
    2059            0 :             new_ke_tot = new_ke_tot + new_dqbar(k)*xh(i_v,k)*xh(i_v,k)
    2060              :          end do
    2061              : 
    2062            0 :          if (abs(old_ke_tot - new_ke_tot) > 1d-7*new_ke_tot) then
    2063            0 :             ierr = -1
    2064            0 :             s% retry_message = 'failed in mesh_adjust do_v'
    2065            0 :             if (s% report_ierr) write(*, *) s% retry_message
    2066              :             !call mesa_error(__FILE__,__LINE__,'do_v')
    2067            0 :             return
    2068              :          end if
    2069              : 
    2070            0 :          err = abs(old_ke_tot - new_ke_tot)/max(new_ke_tot,old_ke_tot,1d0)
    2071            0 :          s% mesh_adjust_KE_conservation = err
    2072              : 
    2073            0 :          if (s% trace_mesh_adjust_error_in_conservation) then
    2074            0 :             write(*,2) 'mesh adjust error in conservation of KE', s% model_number, &
    2075            0 :                err, new_ke_tot, old_ke_tot
    2076            0 :             if (err > 1d-10) then
    2077            0 :                write(*,*) 'err too large'
    2078            0 :                call mesa_error(__FILE__,__LINE__,'do_v')
    2079              :             end if
    2080              :          end if
    2081              : 
    2082              :       end subroutine do_v
    2083              : 
    2084              : 
    2085            0 :       subroutine adjust1_v( &
    2086            0 :             s, k, nz, nz_old, cell_type, comes_from, xout_old, xout_new, &
    2087            0 :             old_dqbar, new_dqbar, old_ke, i_v, xh, xh_old, ierr)
    2088              :          ! set new value for s% v(k) to conserve kinetic energy
    2089              :          type (star_info), pointer :: s
    2090              :          integer, intent(in) :: k, nz, nz_old, i_v
    2091              :          integer, dimension(:) :: cell_type, comes_from
    2092              :          real(dp), dimension(:), intent(in) :: &
    2093              :             xout_old, xout_new, old_dqbar, new_dqbar, old_ke
    2094              :          real(dp), dimension(:,:) :: xh, xh_old
    2095              :          integer, intent(out) :: ierr
    2096              : 
    2097              :          real(dp) :: xq_outer, xq_inner, ke_sum, &
    2098              :             xq0, xq1, new_point_dqbar, dq_sum, dq
    2099              :          integer :: kk, k_outer
    2100              : 
    2101              :          integer, parameter :: k_dbg = -1
    2102              : 
    2103              :          include 'formats'
    2104              : 
    2105            0 :          ierr = 0
    2106              : 
    2107            0 :          if (cell_type(k) == unchanged_type .or. &
    2108              :                cell_type(k) == revised_type) then
    2109            0 :             if (k == 1) then
    2110            0 :                xh(i_v,k) = xh_old(i_v,comes_from(k))
    2111            0 :                return
    2112              :             end if
    2113            0 :             if (cell_type(k-1) == unchanged_type) then
    2114            0 :                xh(i_v,k) = xh_old(i_v,comes_from(k))
    2115            0 :                return
    2116              :             end if
    2117              :          end if
    2118              : 
    2119            0 :          xq_outer = xout_new(k)
    2120            0 :          new_point_dqbar = new_dqbar(k)
    2121            0 :          if (k < nz) then
    2122            0 :             xq_inner = xq_outer + new_point_dqbar
    2123              :          else
    2124            0 :             xq_inner = 1d0
    2125              :          end if
    2126              : 
    2127            0 :          if (k == k_dbg) then
    2128            0 :             write(*,2) 'xq_outer', k, xq_outer
    2129            0 :             write(*,2) 'xq_inner', k, xq_inner
    2130            0 :             write(*,2) 'new_point_dqbar', k, new_point_dqbar
    2131              :          end if
    2132              : 
    2133            0 :          dq_sum = 0d0
    2134            0 :          ke_sum = 0
    2135            0 :          if (xq_outer >= xout_old(nz_old)) then
    2136              :             ! new contained entirely in old center zone
    2137            0 :             k_outer = nz_old
    2138            0 :             if (k == k_dbg) &
    2139            0 :                write(*,2) 'new contained in old center', &
    2140            0 :                   k_outer, xout_old(k_outer)
    2141            0 :          else if (k == 1) then
    2142            0 :             k_outer = 1
    2143              :          else
    2144            0 :             k_outer = comes_from(k-1)
    2145              :          end if
    2146              : 
    2147            0 :          do kk = k_outer, nz_old  ! loop until reach xq_inner
    2148              : 
    2149            0 :             if (kk == nz_old) then
    2150            0 :                xq1 = 1d0
    2151              :             else
    2152            0 :                xq1 = xout_old(kk+1)
    2153              :             end if
    2154            0 :             if (xq1 <= xq_outer) cycle
    2155              : 
    2156            0 :             xq0 = xout_old(kk)
    2157            0 :             if (xq0 >= xq_inner) then
    2158            0 :                if (dq_sum < new_point_dqbar .and. kk > 1) then
    2159              :                   ! need to add a bit more from the previous source
    2160            0 :                   dq = new_point_dqbar - dq_sum
    2161            0 :                   dq_sum = new_point_dqbar
    2162            0 :                   ke_sum = ke_sum + old_ke(kk-1)*dq/old_dqbar(kk-1)
    2163              : 
    2164            0 :                   if (k == k_dbg) &
    2165            0 :                      write(*,3) 'new k contains some of old kk-1', &
    2166            0 :                         k, kk, old_ke(kk-1)*dq, dq_sum
    2167              : 
    2168              :                   end if
    2169              :                exit
    2170              :             end if
    2171              : 
    2172              :             if (xq1 < xq_outer) then
    2173              :                ierr = -1
    2174              :                return
    2175              :             end if
    2176              : 
    2177            0 :             if (xq0 >= xq_outer .and. xq1 <= xq_inner) then  ! entire old kk is in new k
    2178              : 
    2179            0 :                dq = old_dqbar(kk)
    2180            0 :                dq_sum = dq_sum + dq
    2181              : 
    2182            0 :                if (dq_sum > new_point_dqbar) then
    2183              :                   ! dq too large -- numerical roundoff problems
    2184            0 :                   dq = dq - (new_point_dqbar - dq_sum)
    2185            0 :                   dq_sum = new_point_dqbar
    2186              :                end if
    2187              : 
    2188            0 :                ke_sum = ke_sum + old_ke(kk)*dq/old_dqbar(kk)
    2189              : 
    2190            0 :                if (k == k_dbg) &
    2191            0 :                   write(*,3) 'new k contains all of old kk', &
    2192            0 :                      k, kk, old_ke(kk)*dq, ke_sum
    2193              : 
    2194            0 :             else if (xq0 <= xq_outer .and. xq1 >= xq_inner) then  ! entire new k is in old kk
    2195              : 
    2196            0 :                dq = new_dqbar(k)
    2197            0 :                dq_sum = dq_sum + dq
    2198            0 :                ke_sum = ke_sum + old_ke(kk)*dq/old_dqbar(kk)
    2199              : 
    2200            0 :                if (k == k_dbg) &
    2201            0 :                   write(*,3) 'all new k is in old kk', &
    2202            0 :                      k, kk, old_ke(kk)*dq, ke_sum
    2203              : 
    2204              :             else  ! only use the part of old kk that is in new k
    2205              : 
    2206            0 :                if (k == k_dbg) then
    2207            0 :                   write(*,*) 'only use the part of old kk that is in new k', xq_inner <= xq1
    2208            0 :                   write(*,1) 'xq_outer', xq_outer
    2209            0 :                   write(*,1) 'xq_inner', xq_inner
    2210            0 :                   write(*,1) 'xq0', xq0
    2211            0 :                   write(*,1) 'xq1', xq1
    2212            0 :                   write(*,1) 'dq_sum', dq_sum
    2213            0 :                   write(*,1) 'new_point_dqbar', new_point_dqbar
    2214            0 :                   write(*,1) 'new_point_dqbar - dq_sum', new_point_dqbar - dq_sum
    2215              :                end if
    2216              : 
    2217            0 :                if (xq_inner <= xq1) then  ! this is the last part of new k
    2218              : 
    2219            0 :                   dq = new_point_dqbar - dq_sum
    2220            0 :                   dq_sum = new_point_dqbar
    2221              : 
    2222              :                else  ! we avoid this case if possible because of numerical roundoff
    2223              : 
    2224            0 :                   if (k == k_dbg) write(*,3) 'we avoid this case if possible', k, kk
    2225              : 
    2226            0 :                   dq = max(0d0, xq1 - xq_outer)
    2227            0 :                   if (dq_sum + dq > new_point_dqbar) dq = new_point_dqbar - dq_sum
    2228            0 :                   dq_sum = dq_sum + dq
    2229              : 
    2230              :                end if
    2231              : 
    2232            0 :                if (k == k_dbg) then
    2233            0 :                   write(*,3) 'new k use only part of old kk', k, kk
    2234            0 :                   write(*,2) 'dq_sum', k, dq_sum
    2235            0 :                   write(*,2) 'dq', k, dq
    2236            0 :                   write(*,2) 'old_ke(kk)', kk, old_ke(kk)
    2237            0 :                   write(*,2) 'old ke_sum', k, ke_sum
    2238            0 :                   write(*,2) 'new ke_sum', k, ke_sum + old_ke(kk)*dq
    2239              :                end if
    2240              : 
    2241            0 :                ke_sum = ke_sum + old_ke(kk)*dq/old_dqbar(kk)
    2242              : 
    2243            0 :                if (dq <= 0) then
    2244            0 :                   ierr = -1
    2245              :                   !return
    2246            0 :                   write(*,*) 'dq <= 0', dq
    2247            0 :                   call mesa_error(__FILE__,__LINE__,'debugging: adjust1_v')
    2248              :                end if
    2249              : 
    2250              :             end if
    2251              : 
    2252            0 :             if (dq_sum >= new_point_dqbar) then
    2253              :                exit
    2254              :             end if
    2255              : 
    2256              :          end do
    2257              : 
    2258            0 :          xh(i_v,k) = sqrt(ke_sum/new_point_dqbar)  ! we have skipped the 1/2 xmstar factor
    2259            0 :          if (xh_old(i_v,comes_from(k)) < 0d0) xh(i_v,k) = -xh(i_v,k)
    2260              : 
    2261            0 :          if (k == k_dbg) then
    2262            0 : !$OMP critical (adjust1_v_dbg)
    2263            0 :             write(*,2) 'xh(i_v,k) new_dqbar', k, xh(i_v,k), new_dqbar(k)
    2264            0 :             write(*,2) 'xh_old(i_v,comes_from(k)) old_dqbar', &
    2265            0 :                comes_from(k), xh_old(i_v,comes_from(k)), old_dqbar(comes_from(k))
    2266            0 :             if (k == k_dbg) call mesa_error(__FILE__,__LINE__,'adjust1_v')
    2267              : !$OMP end critical (adjust1_v_dbg)
    2268              :             !stop
    2269              :          end if
    2270              : 
    2271              :       end subroutine adjust1_v
    2272              : 
    2273              : 
    2274            0 :       subroutine do_u( &
    2275            0 :             s, nz, nz_old, cell_type, comes_from, &
    2276            0 :             old_xq, new_xq, old_dq, new_dq, xh, xh_old, &
    2277            0 :             xout_old, xout_new, old_ke, ierr)
    2278              :          use alloc
    2279              :          type (star_info), pointer :: s
    2280              :          integer, intent(in) :: nz, nz_old
    2281              :          integer, dimension(:) :: cell_type, comes_from
    2282              :          real(dp), dimension(:) :: &
    2283              :             xout_old, xout_new, old_xq, new_xq, old_dq, new_dq, old_ke
    2284              :          real(dp), dimension(:,:) :: xh, xh_old
    2285              :          integer, intent(out) :: ierr
    2286              : 
    2287              :          integer :: k, op_err, i_u
    2288              :          real(dp) :: old_ke_tot, new_ke_tot, xmstar, err
    2289              : 
    2290              :          include 'formats'
    2291            0 :          ierr = 0
    2292            0 :          i_u = s% i_u
    2293            0 :          xmstar = s% xmstar
    2294              : 
    2295            0 :          old_ke_tot = 0d0
    2296            0 :          do k=1,nz_old  ! skip common factor 1/2 xmstar in ke
    2297            0 :             old_ke(k) = old_dq(k)*xh_old(i_u,k)*xh_old(i_u,k)
    2298            0 :             old_ke_tot = old_ke_tot + old_ke(k)
    2299              :          end do
    2300              : 
    2301            0 : !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
    2302              :          do k = 1, nz
    2303              :             op_err = 0
    2304              :             call adjust1_u( &
    2305              :                s, k, nz, nz_old, cell_type, comes_from, xout_old, xout_new, &
    2306              :                old_dq, new_dq, old_ke, i_u, xh, xh_old, op_err)
    2307              :             if (op_err /= 0) ierr = op_err
    2308              :          end do
    2309              : !$OMP END PARALLEL DO
    2310            0 :          if (ierr /= 0) then
    2311            0 :             return
    2312              :          end if
    2313              : 
    2314            0 :          new_ke_tot = 0
    2315            0 :          do k=1,nz
    2316            0 :             new_ke_tot = new_ke_tot + new_dq(k)*xh(i_u,k)*xh(i_u,k)
    2317              :          end do
    2318              : 
    2319            0 :          err = abs(old_ke_tot - new_ke_tot)/max(new_ke_tot,old_ke_tot,1d0)
    2320            0 :          s% mesh_adjust_KE_conservation = err
    2321              : 
    2322            0 :          if (s% trace_mesh_adjust_error_in_conservation) then
    2323            0 :             write(*,2) 'mesh adjust error in conservation of KE', s% model_number, &
    2324            0 :                err, new_ke_tot, old_ke_tot
    2325            0 :             if (err > 1d-10) then
    2326            0 :                write(*,*) 'err too large'
    2327            0 :                call mesa_error(__FILE__,__LINE__,'do_u')
    2328              :             end if
    2329              :          end if
    2330              : 
    2331              :       end subroutine do_u
    2332              : 
    2333              : 
    2334            0 :       subroutine adjust1_u( &
    2335            0 :             s, k, nz, nz_old, cell_type, comes_from, xout_old, xout_new, &
    2336            0 :             old_dq, new_dq, old_ke, i_u, xh, xh_old, ierr)
    2337              :          ! set new value for s% u(k) to conserve kinetic energy
    2338              :          type (star_info), pointer :: s
    2339              :          integer, intent(in) :: k, nz, nz_old, i_u
    2340              :          integer, dimension(:) :: cell_type, comes_from
    2341              :          real(dp), dimension(:), intent(in) :: &
    2342              :             xout_old, xout_new, old_dq, new_dq, old_ke
    2343              :          real(dp), dimension(:,:) :: xh, xh_old
    2344              :          integer, intent(out) :: ierr
    2345              : 
    2346              :          real(dp) :: xq_outer, xq_inner, ke_sum, &
    2347              :             xq0, xq1, new_cell_dq, dq_sum, dq
    2348              :          integer :: kk, k_outer
    2349              : 
    2350              :          integer, parameter :: k_dbg = -1
    2351              : 
    2352              :          include 'formats'
    2353              : 
    2354            0 :          ierr = 0
    2355              : 
    2356            0 :          if (cell_type(k) == unchanged_type .or. &
    2357              :                cell_type(k) == revised_type) then
    2358            0 :             if (k == 1) then
    2359            0 :                xh(i_u,k) = xh_old(i_u,comes_from(k))
    2360            0 :                return
    2361              :             end if
    2362            0 :             if (cell_type(k-1) == unchanged_type) then
    2363            0 :                xh(i_u,k) = xh_old(i_u,comes_from(k))
    2364            0 :                return
    2365              :             end if
    2366              :          end if
    2367              : 
    2368            0 :          xq_outer = xout_new(k)
    2369            0 :          new_cell_dq = new_dq(k)
    2370            0 :          if (k < nz) then
    2371            0 :             xq_inner = xq_outer + new_cell_dq
    2372              :          else
    2373            0 :             xq_inner = 1d0
    2374              :          end if
    2375              : 
    2376            0 :          if (k == k_dbg) then
    2377            0 :             write(*,2) 'xq_outer', k, xq_outer
    2378            0 :             write(*,2) 'xq_inner', k, xq_inner
    2379            0 :             write(*,2) 'new_cell_dq', k, new_cell_dq
    2380              :          end if
    2381              : 
    2382            0 :          dq_sum = 0d0
    2383            0 :          ke_sum = 0
    2384            0 :          if (xq_outer >= xout_old(nz_old)) then
    2385              :             ! new contained entirely in old center zone
    2386            0 :             k_outer = nz_old
    2387            0 :             if (k == k_dbg) &
    2388            0 :                write(*,2) 'new contained in old center', &
    2389            0 :                   k_outer, xout_old(k_outer)
    2390            0 :          else if (k == 1) then
    2391            0 :             k_outer = 1
    2392              :          else
    2393            0 :             k_outer = comes_from(k-1)
    2394              :          end if
    2395              : 
    2396            0 :          do kk = k_outer, nz_old  ! loop until reach xq_inner
    2397              : 
    2398            0 :             if (kk == nz_old) then
    2399            0 :                xq1 = 1d0
    2400              :             else
    2401            0 :                xq1 = xout_old(kk+1)
    2402              :             end if
    2403            0 :             if (xq1 <= xq_outer) cycle
    2404              : 
    2405              :             if (xq1 < xq_outer) then
    2406              :                ierr = -1
    2407              :                return
    2408              :             end if
    2409              : 
    2410            0 :             xq0 = xout_old(kk)
    2411            0 :             if (xq0 >= xq_outer .and. xq1 <= xq_inner) then  ! entire old kk is in new k
    2412              : 
    2413            0 :                dq = old_dq(kk)
    2414            0 :                dq_sum = dq_sum + dq
    2415              : 
    2416            0 :                if (dq_sum > new_cell_dq) then
    2417              :                   ! dq too large -- numerical roundoff problems
    2418            0 :                   dq = dq - (new_cell_dq - dq_sum)
    2419            0 :                   dq_sum = new_cell_dq
    2420              :                end if
    2421              : 
    2422            0 :                ke_sum = ke_sum + old_ke(kk)*dq/old_dq(kk)
    2423              : 
    2424            0 :                if (k == k_dbg) &
    2425            0 :                   write(*,3) 'new k contains all of old kk', &
    2426            0 :                      k, kk, old_ke(kk)*dq, ke_sum
    2427              : 
    2428            0 :             else if (xq0 <= xq_outer .and. xq1 >= xq_inner) then  ! entire new k is in old kk
    2429              : 
    2430            0 :                dq = new_dq(k)
    2431            0 :                dq_sum = dq_sum + dq
    2432            0 :                ke_sum = ke_sum + old_ke(kk)*dq/old_dq(kk)
    2433              : 
    2434            0 :                if (k == k_dbg) &
    2435            0 :                   write(*,3) 'all new k is in old kk', &
    2436            0 :                      k, kk, old_ke(kk)*dq, ke_sum
    2437              : 
    2438              :             else  ! only use the part of old kk that is in new k
    2439              : 
    2440            0 :                if (k == k_dbg) then
    2441            0 :                   write(*,*) 'only use the part of old kk that is in new k', xq_inner <= xq1
    2442            0 :                   write(*,1) 'xq_outer', xq_outer
    2443            0 :                   write(*,1) 'xq_inner', xq_inner
    2444            0 :                   write(*,1) 'xq0', xq0
    2445            0 :                   write(*,1) 'xq1', xq1
    2446            0 :                   write(*,1) 'dq_sum', dq_sum
    2447            0 :                   write(*,1) 'new_cell_dq', new_cell_dq
    2448            0 :                   write(*,1) 'new_cell_dq - dq_sum', new_cell_dq - dq_sum
    2449              :                end if
    2450              : 
    2451            0 :                if (xq_inner <= xq1) then  ! this is the last part of new k
    2452              : 
    2453            0 :                   dq = new_cell_dq - dq_sum
    2454            0 :                   dq_sum = new_cell_dq
    2455              : 
    2456              :                else  ! we avoid this case if possible because of numerical roundoff
    2457              : 
    2458            0 :                   if (k == k_dbg) write(*,3) 'we avoid this case if possible', k, kk
    2459              : 
    2460            0 :                   dq = max(0d0, xq1 - xq_outer)
    2461            0 :                   if (dq_sum + dq > new_cell_dq) dq = new_cell_dq - dq_sum
    2462            0 :                   dq_sum = dq_sum + dq
    2463              : 
    2464              :                end if
    2465              : 
    2466            0 :                if (k == k_dbg) then
    2467            0 :                   write(*,3) 'new k use only part of old kk', k, kk
    2468            0 :                   write(*,2) 'dq_sum', k, dq_sum
    2469            0 :                   write(*,2) 'dq', k, dq
    2470            0 :                   write(*,2) 'old_ke(kk)', kk, old_ke(kk)
    2471            0 :                   write(*,2) 'old ke_sum', k, ke_sum
    2472            0 :                   write(*,2) 'new ke_sum', k, ke_sum + old_ke(kk)*dq
    2473              :                end if
    2474              : 
    2475            0 :                ke_sum = ke_sum + old_ke(kk)*dq/old_dq(kk)
    2476              : 
    2477            0 :                if (dq <= 0) then
    2478            0 :                   ierr = -1
    2479              :                   !return
    2480            0 :                   write(*,*) 'dq <= 0', dq
    2481            0 :                   call mesa_error(__FILE__,__LINE__,'debugging: adjust1_u')
    2482              :                end if
    2483              : 
    2484              :             end if
    2485              : 
    2486            0 :             if (dq_sum >= new_cell_dq) then
    2487              :                exit
    2488              :             end if
    2489              : 
    2490              :          end do
    2491              : 
    2492            0 :          xh(i_u,k) = sqrt(ke_sum/new_cell_dq)  ! we have skipped the 1/2 xmstar factor
    2493            0 :          if (xh_old(i_u,comes_from(k)) < 0d0) xh(i_u,k) = -xh(i_u,k)
    2494              : 
    2495            0 :          if (k == k_dbg) then
    2496            0 : !$OMP critical (adjust1_u_dbg)
    2497            0 :             write(*,2) 'xh(i_u,k) new_dq', k, xh(i_u,k), new_dq(k)
    2498            0 :             write(*,2) 'xh_old(i_u,comes_from(k)) old_dq', &
    2499            0 :                comes_from(k), xh_old(i_u,comes_from(k)), old_dq(comes_from(k))
    2500            0 :             if (k == k_dbg) call mesa_error(__FILE__,__LINE__,'adjust1_u')
    2501              : !$OMP end critical (adjust1_u_dbg)
    2502              :             !stop
    2503              :          end if
    2504              : 
    2505              :       end subroutine adjust1_u
    2506              : 
    2507              : 
    2508            0 :       subroutine do_Hp_face( &
    2509              :             s, nz, nz_old, nzlo, nzhi, comes_from, xh, xh_old, &
    2510            0 :             xq, xq_old_plus1, xq_new, work, Hp_face_old_plus1, Hp_face_new, ierr)
    2511              :          use interp_1d_def
    2512              :          use interp_1d_lib
    2513              :          type (star_info), pointer :: s
    2514              :          integer, intent(in) :: nz, nz_old, nzlo, nzhi, comes_from(:)
    2515              :          real(dp), dimension(:,:), pointer :: xh, xh_old
    2516              :          real(dp), dimension(:), pointer :: work
    2517              :          real(dp), dimension(:) :: &
    2518              :             xq, xq_old_plus1, Hp_face_old_plus1, Hp_face_new, xq_new
    2519              :          integer, intent(out) :: ierr
    2520              : 
    2521              :          integer :: n, i_Hp, k
    2522              : 
    2523              :          include 'formats'
    2524              : 
    2525            0 :          ierr = 0
    2526            0 :          i_Hp = s% i_Hp
    2527            0 :          if (i_Hp == 0) return
    2528            0 :          n = nzhi - nzlo + 1
    2529              : 
    2530            0 :          do k=1,nz_old
    2531            0 :             Hp_face_old_plus1(k) = xh_old(i_Hp,k)
    2532              :          end do
    2533            0 :          Hp_face_old_plus1(nz_old+1) = Hp_face_old_plus1(nz_old)
    2534              : 
    2535              :          call interpolate_vector( &
    2536              :                nz_old+1, xq_old_plus1, n, xq_new, &
    2537              :                Hp_face_old_plus1, Hp_face_new, interp_pm, nwork, work, &
    2538            0 :                'mesh_adjust do_Hp_face', ierr)
    2539            0 :          if (ierr /= 0) then
    2540              :             return
    2541              :             write(*,*) 'interpolate_vector failed in do_Hp_face for remesh'
    2542              :             call mesa_error(__FILE__,__LINE__,'debug: mesh adjust: do_Hp_face')
    2543              :          end if
    2544              : 
    2545            0 :          do k=nzlo,nzhi
    2546            0 :             xh(i_Hp,k) = Hp_face_new(k+1-nzlo)
    2547              :          end do
    2548              : 
    2549            0 :          n = nzlo - 1
    2550            0 :          if (n > 0) then
    2551            0 :             do k=1,n
    2552            0 :                xh(i_Hp,k) = xh_old(i_Hp,k)
    2553              :             end do
    2554              :          end if
    2555              : 
    2556            0 :          if (nzhi < nz) then
    2557            0 :             n = nz - nzhi - 1  ! nz-n = nzhi+1
    2558            0 :             do k=0,n
    2559            0 :                xh(i_Hp,nz-k) = xh_old(i_Hp,nz_old-k)
    2560              :             end do
    2561              :          end if
    2562              : 
    2563              :       end subroutine do_Hp_face
    2564              : 
    2565              : 
    2566            0 :       subroutine do_etrb( &  ! same logic as do_u
    2567            0 :             s, nz, nz_old, cell_type, comes_from, &
    2568            0 :             old_xq, new_xq, old_dq, new_dq, xh, xh_old, &
    2569            0 :             xout_old, xout_new, old_eturb, ierr)
    2570              :          use alloc
    2571              :          type (star_info), pointer :: s
    2572              :          integer, intent(in) :: nz, nz_old
    2573              :          integer, dimension(:) :: cell_type, comes_from
    2574              :          real(dp), dimension(:) :: &
    2575              :             xout_old, xout_new, old_xq, new_xq, old_dq, new_dq, old_eturb
    2576              :          real(dp), dimension(:,:) :: xh, xh_old
    2577              :          integer, intent(out) :: ierr
    2578              : 
    2579              :          integer :: k, op_err, i_w
    2580              :          real(dp) :: old_eturb_tot, new_eturb_tot, xmstar, err
    2581              : 
    2582              :          include 'formats'
    2583            0 :          ierr = 0
    2584            0 :          i_w = s% i_w
    2585            0 :          xmstar = s% xmstar
    2586              : 
    2587            0 :          old_eturb_tot = 0d0
    2588            0 :          do k=1,nz_old
    2589            0 :             old_eturb(k) = old_dq(k)*pow2(xh_old(i_w,k))
    2590            0 :             old_eturb_tot = old_eturb_tot + old_eturb(k)
    2591              :          end do
    2592              : 
    2593            0 : !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
    2594              :          do k = 1, nz
    2595              :             op_err = 0
    2596              :             call adjust1_etrb( &
    2597              :                s, k, nz, nz_old, cell_type, comes_from, xout_old, xout_new, &
    2598              :                old_dq, new_dq, old_eturb, i_w, xh, xh_old, op_err)
    2599              :             if (op_err /= 0) ierr = op_err
    2600              :          end do
    2601              : !$OMP END PARALLEL DO
    2602            0 :          if (ierr /= 0) then
    2603            0 :             return
    2604              :          end if
    2605              : 
    2606            0 :          new_eturb_tot = 0
    2607            0 :          do k=1,nz
    2608            0 :             new_eturb_tot = new_eturb_tot + new_dq(k)*pow2(xh(i_w,k))
    2609              :          end do
    2610              : 
    2611            0 :          err = abs(old_eturb_tot - new_eturb_tot)/max(new_eturb_tot,old_eturb_tot,1d0)
    2612            0 :          s% mesh_adjust_Eturb_conservation = err
    2613              : 
    2614            0 :          if (s% trace_mesh_adjust_error_in_conservation) then
    2615            0 :             write(*,2) 'mesh adjust error in conservation of turbulent energy', s% model_number, &
    2616            0 :                err, new_eturb_tot, old_eturb_tot
    2617            0 :             if (err > 1d-10) then
    2618            0 :                write(*,*) 'err too large'
    2619            0 :                call mesa_error(__FILE__,__LINE__,'do_etrb')
    2620              :             end if
    2621              :          end if
    2622              : 
    2623              :       end subroutine do_etrb
    2624              : 
    2625              : 
    2626            0 :       subroutine adjust1_etrb( &
    2627            0 :             s, k, nz, nz_old, cell_type, comes_from, xout_old, xout_new, &
    2628            0 :             old_dq, new_dq, old_eturb, i_w, xh, xh_old, ierr)
    2629              :          ! set new value for s% w(k) to conserve turbulent energy
    2630              :          type (star_info), pointer :: s
    2631              :          integer, intent(in) :: k, nz, nz_old, i_w
    2632              :          integer, dimension(:) :: cell_type, comes_from
    2633              :          real(dp), dimension(:), intent(in) :: &
    2634              :             xout_old, xout_new, old_dq, new_dq, old_eturb
    2635              :          real(dp), dimension(:,:) :: xh, xh_old
    2636              :          integer, intent(out) :: ierr
    2637              : 
    2638              :          real(dp) :: xq_outer, xq_inner, eturb_sum, &
    2639              :             xq0, xq1, new_cell_dq, dq_sum, dq
    2640              :          integer :: kk, k_outer
    2641              : 
    2642              :          integer, parameter :: k_dbg = -1
    2643              : 
    2644              :          include 'formats'
    2645              : 
    2646            0 :          ierr = 0
    2647              : 
    2648            0 :          if (cell_type(k) == unchanged_type .or. &
    2649              :                cell_type(k) == revised_type) then
    2650              :             ! just copy the old value
    2651            0 :             if (k == 1) then
    2652            0 :                xh(i_w,k) = xh_old(i_w,comes_from(k))
    2653            0 :                return
    2654              :             end if
    2655            0 :             if (cell_type(k-1) == unchanged_type) then
    2656            0 :                xh(i_w,k) = xh_old(i_w,comes_from(k))
    2657            0 :                return
    2658              :             end if
    2659              :          end if
    2660              : 
    2661            0 :          xq_outer = xout_new(k)
    2662            0 :          new_cell_dq = new_dq(k)
    2663            0 :          if (k < nz) then
    2664            0 :             xq_inner = xq_outer + new_cell_dq
    2665              :          else
    2666            0 :             xq_inner = 1d0
    2667              :          end if
    2668              : 
    2669            0 :          if (k == k_dbg) then
    2670            0 :             write(*,2) 'xq_outer', k, xq_outer
    2671            0 :             write(*,2) 'xq_inner', k, xq_inner
    2672            0 :             write(*,2) 'new_cell_dq', k, new_cell_dq
    2673              :          end if
    2674              : 
    2675            0 :          dq_sum = 0d0
    2676            0 :          eturb_sum = 0
    2677            0 :          if (xq_outer >= xout_old(nz_old)) then
    2678              :             ! new contained entirely in old center zone
    2679            0 :             k_outer = nz_old
    2680            0 :             if (k == k_dbg) &
    2681            0 :                write(*,2) 'new contained in old center', &
    2682            0 :                   k_outer, xout_old(k_outer)
    2683            0 :          else if (k == 1) then
    2684            0 :             k_outer = 1
    2685              :          else
    2686            0 :             k_outer = comes_from(k-1)
    2687              :          end if
    2688              : 
    2689            0 :          do kk = k_outer, nz_old  ! loop until reach xq_inner
    2690              : 
    2691            0 :             if (kk == nz_old) then
    2692            0 :                xq1 = 1d0
    2693              :             else
    2694            0 :                xq1 = xout_old(kk+1)
    2695              :             end if
    2696            0 :             if (xq1 <= xq_outer) cycle
    2697              : 
    2698              :             if (xq1 < xq_outer) then
    2699              :                ierr = -1
    2700              :                return
    2701              :             end if
    2702              : 
    2703            0 :             xq0 = xout_old(kk)
    2704            0 :             if (xq0 >= xq_outer .and. xq1 <= xq_inner) then  ! entire old kk is in new k
    2705              : 
    2706            0 :                dq = old_dq(kk)
    2707            0 :                dq_sum = dq_sum + dq
    2708              : 
    2709            0 :                if (dq_sum > new_cell_dq) then
    2710              :                   ! dq too large -- numerical roundoff problems
    2711            0 :                   dq = dq - (new_cell_dq - dq_sum)
    2712            0 :                   dq_sum = new_cell_dq
    2713              :                end if
    2714              : 
    2715            0 :                eturb_sum = eturb_sum + old_eturb(kk)*dq/old_dq(kk)
    2716              : 
    2717            0 :                if (k == k_dbg) &
    2718            0 :                   write(*,3) 'new k contains all of old kk', &
    2719            0 :                      k, kk, old_eturb(kk)*dq, eturb_sum
    2720              : 
    2721            0 :             else if (xq0 <= xq_outer .and. xq1 >= xq_inner) then  ! entire new k is in old kk
    2722              : 
    2723            0 :                dq = new_dq(k)
    2724            0 :                dq_sum = dq_sum + dq
    2725            0 :                eturb_sum = eturb_sum + old_eturb(kk)*dq/old_dq(kk)
    2726              : 
    2727            0 :                if (k == k_dbg) &
    2728            0 :                   write(*,3) 'all new k is in old kk', &
    2729            0 :                      k, kk, old_eturb(kk)*dq, eturb_sum
    2730              : 
    2731              :             else  ! only use the part of old kk that is in new k
    2732              : 
    2733            0 :                if (k == k_dbg) then
    2734            0 :                   write(*,*) 'only use the part of old kk that is in new k', xq_inner <= xq1
    2735            0 :                   write(*,1) 'xq_outer', xq_outer
    2736            0 :                   write(*,1) 'xq_inner', xq_inner
    2737            0 :                   write(*,1) 'xq0', xq0
    2738            0 :                   write(*,1) 'xq1', xq1
    2739            0 :                   write(*,1) 'dq_sum', dq_sum
    2740            0 :                   write(*,1) 'new_cell_dq', new_cell_dq
    2741            0 :                   write(*,1) 'new_cell_dq - dq_sum', new_cell_dq - dq_sum
    2742              :                end if
    2743              : 
    2744            0 :                if (xq_inner <= xq1) then  ! this is the last part of new k
    2745              : 
    2746            0 :                   dq = new_cell_dq - dq_sum
    2747            0 :                   dq_sum = new_cell_dq
    2748              : 
    2749              :                else  ! we avoid this case if possible because of numerical roundoff
    2750              : 
    2751            0 :                   if (k == k_dbg) write(*,3) 'we avoid this case if possible', k, kk
    2752              : 
    2753            0 :                   dq = max(0d0, xq1 - xq_outer)
    2754            0 :                   if (dq_sum + dq > new_cell_dq) dq = new_cell_dq - dq_sum
    2755            0 :                   dq_sum = dq_sum + dq
    2756              : 
    2757              :                end if
    2758              : 
    2759            0 :                if (k == k_dbg) then
    2760            0 :                   write(*,3) 'new k use only part of old kk', k, kk
    2761            0 :                   write(*,2) 'dq_sum', k, dq_sum
    2762            0 :                   write(*,2) 'dq', k, dq
    2763            0 :                   write(*,2) 'old_eturb(kk)', kk, old_eturb(kk)
    2764            0 :                   write(*,2) 'old eturb_sum', k, eturb_sum
    2765            0 :                   write(*,2) 'new eturb_sum', k, eturb_sum + old_eturb(kk)*dq
    2766              :                end if
    2767              : 
    2768            0 :                eturb_sum = eturb_sum + old_eturb(kk)*dq/old_dq(kk)
    2769              : 
    2770            0 :                if (dq <= 0) then
    2771            0 :                   ierr = -1
    2772              :                   !return
    2773            0 :                   write(*,*) 'dq <= 0', dq
    2774            0 :                   call mesa_error(__FILE__,__LINE__,'debugging: adjust1_etrb')
    2775              :                end if
    2776              : 
    2777              :             end if
    2778              : 
    2779            0 :             if (dq_sum >= new_cell_dq) then
    2780              :                exit
    2781              :             end if
    2782              : 
    2783              :          end do
    2784              : 
    2785            0 :          xh(i_w,k) = sqrt(max(0d0,eturb_sum/new_cell_dq))
    2786              : 
    2787              :       end subroutine adjust1_etrb
    2788              : 
    2789              :       end module mesh_adjust
        

Generated by: LCOV version 2.0-1