LCOV - code coverage report
Current view: top level - star/private - mesh_plan.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 61.0 % 531 324
Test Date: 2025-05-08 18:23:42 Functions: 90.9 % 11 10

            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_plan
      21              : 
      22              :       use const_def, only: dp, convective_mixing
      23              :       use num_lib
      24              :       use utils_lib
      25              :       use star_private_def
      26              : 
      27              :       implicit none
      28              : 
      29              :       private
      30              :       public :: do_mesh_plan
      31              : 
      32              :       logical, parameter :: plan_dbg = .false.
      33              :       integer, parameter :: kdbg = -1
      34              : 
      35              :       contains
      36              : 
      37           10 :       subroutine do_mesh_plan( &
      38              :             s, nz_old, max_allowed_nz, okay_to_merge, D_mix, &
      39              :             max_k_old_for_split_in, min_k_old_for_split_in, xq_old, dq_old, &
      40              :             min_dq_in, max_dq, min_dq_for_split, mesh_max_allowed_ratio, &
      41              :             do_not_split, num_gvals, gval_names, &
      42              :             gval_is_xa_function, gval_is_logT_function, gvals, &
      43              :             delta_gval_max, max_center_cell_dq, max_surface_cell_dq, &
      44              :             max_num_subcells, max_num_merge_cells, &
      45              :             nz_new, xq_new, dq_new, which_gval, comes_from, ierr)
      46              :          ! return keep_going, or terminate
      47              :          use mesh_functions, only: max_allowed_gvals
      48              :          ! inputs
      49              :          type (star_info), pointer :: s
      50              :          integer, intent(in) :: nz_old, max_allowed_nz, max_num_subcells, &
      51              :             max_num_merge_cells, max_k_old_for_split_in, min_k_old_for_split_in
      52              :          logical, intent(in) :: okay_to_merge
      53              :          real(dp), pointer :: D_mix(:)  ! (nz_old)
      54              :          real(dp), pointer :: xq_old(:)  ! (nz_old)
      55              :          real(dp), pointer :: dq_old(:)  ! (nz_old)
      56              :          real(dp), intent(in) :: min_dq_in, max_dq, min_dq_for_split, mesh_max_allowed_ratio
      57              :          logical, pointer :: do_not_split(:)
      58              :          integer, intent(in) :: num_gvals
      59              :          character (len=32) :: gval_names(max_allowed_gvals)
      60              :          logical, dimension(max_allowed_gvals) :: gval_is_xa_function, gval_is_logT_function
      61              :          real(dp), pointer :: gvals(:,:)  ! (nz_old, num_gvals)
      62              :          real(dp), pointer :: delta_gval_max(:)  ! (nz_old)
      63              :          real(dp), intent(in) :: max_center_cell_dq, max_surface_cell_dq
      64              :          ! outputs
      65              :          integer, intent(out) :: nz_new
      66              :          real(dp), pointer :: xq_new(:), dq_new(:)  ! (nz_new)
      67              :             ! must be allocated on entry; suggested size >= nz_old.
      68              :             ! reallocated as necessary if need to enlarge.
      69              :             ! size on return is >= nz_new.
      70              :          integer, pointer :: which_gval(:)  ! (nz_new)  for debugging.
      71              :             ! which_gval(k) = gval number that set the size for new cell k.
      72              :             ! size may have been reduced below gradient setting by other restrictions.
      73              :          integer, pointer :: comes_from(:)  ! (nz_new)
      74              :             ! xq_old(comes_from(k)+1) > xq_new(k) >= xq_old(comes_from(k)), if comes_from(k) < nz_old.
      75              :          integer, intent(out) :: ierr
      76              : 
      77              :          integer :: j, k, k_old, k_new, nz, new_capacity, iounit, species, &
      78              :             max_num_merge_surface_cells, max_k_old_for_split, min_k_old_for_split
      79           10 :          real(dp) :: D_mix_cutoff, next_xq, next_dq, max_dq_cntr, &
      80           10 :             dq_sum, min_dq, min_dq_for_xa, min_dq_for_logT
      81              : 
      82              :          logical, parameter :: write_plan_debug = .false.
      83              : 
      84              :          include 'formats'
      85              : 
      86           10 :          ierr = 0
      87              : 
      88           10 :          min_dq = min_dq_in
      89              : 
      90           10 :          if (max_k_old_for_split_in < 0) then
      91            0 :             max_k_old_for_split = nz_old + max_k_old_for_split_in
      92              :          else
      93           10 :             max_k_old_for_split = max_k_old_for_split_in
      94              :          end if
      95              : 
      96           10 :          if (min_k_old_for_split_in < 0) then
      97            0 :             min_k_old_for_split = nz_old + min_k_old_for_split_in
      98              :          else
      99           10 :             min_k_old_for_split = min_k_old_for_split_in
     100              :          end if
     101              : 
     102           10 :          max_num_merge_surface_cells = max_num_merge_cells  ! for now
     103              : 
     104           10 :          if (max_dq < min_dq) then
     105            0 :             write(*,1) 'ERROR in controls: max_dq < min_dq', max_dq, min_dq
     106            0 :             ierr = -1
     107            0 :             return
     108              :          end if
     109              : 
     110           10 :          if (max_center_cell_dq < min_dq) then
     111            0 :             write(*,1) 'ERROR in controls: max_center_cell_dq < min_dq', max_center_cell_dq, min_dq
     112            0 :             ierr = -1
     113            0 :             return
     114              :          end if
     115              : 
     116           10 :          if (max_surface_cell_dq < min_dq) then
     117            0 :             write(*,1) 'ERROR in controls: max_surface_cell_dq < min_dq', max_surface_cell_dq, min_dq
     118            0 :             ierr = -1
     119            0 :             return
     120              :          end if
     121              : 
     122        12095 :          do k = 2, nz_old
     123        12095 :             if (xq_old(k) <= xq_old(k-1)) then
     124            0 :                write(*,3) 'bad xq_old', k, nz_old, xq_old(k), xq_old(k-1)
     125            0 :                ierr = -1
     126            0 :                return
     127              :             end if
     128              :          end do
     129              : 
     130           10 :          if (s% set_min_D_mix) then
     131              :             D_mix_cutoff = s% min_D_mix
     132              :          else
     133           10 :             D_mix_cutoff = 0
     134              :          end if
     135              : 
     136              :          if (write_plan_debug) call open_debug_file
     137              : 
     138              :          if (plan_dbg) then
     139              :             write(*,*) 'num_gvals', num_gvals
     140              :             do j=1,num_gvals
     141              :                write(*,*) j, trim(gval_names(j))
     142              :             end do
     143              :             write(*,'(A)')
     144              :          end if
     145              : 
     146           10 :          nz = nz_old
     147           10 :          species = s% species
     148              : 
     149              :          new_capacity = min(size(xq_new,dim=1), size(dq_new,dim=1), &
     150           10 :                   size(which_gval,dim=1), size(comes_from,dim=1))
     151           10 :          max_dq_cntr = max(1d-20, max_center_cell_dq, 0.75d0*dq_old(nz_old))
     152              : 
     153        12105 :          comes_from(1:nz) = 0
     154           10 :          comes_from(1) = 1
     155              : 
     156           10 :          call pick_new_points(s, ierr)
     157           10 :          if (ierr /= 0) return
     158              : 
     159           10 :          if (min_k_old_for_split <= 1) then
     160           10 :             do while (dq_new(1) > max(max_surface_cell_dq,2*min_dq,min_dq_for_split))
     161            0 :                call split1(1, ierr)
     162           10 :                if (ierr /= 0) then
     163            0 :                   write(*,*) 'failed trying to split surface cell'
     164            0 :                   stop
     165              :                   return
     166              :                end if
     167              :             end do
     168              :          end if
     169              : 
     170           10 :          call smooth_new_points(ierr)  ! split as necessary
     171           10 :          if (ierr /= 0) return
     172              : 
     173              :          if (write_plan_debug) then
     174              :             close(iounit)
     175              :          end if
     176              : 
     177           10 :          if (ierr /= 0) return
     178              : 
     179              : 
     180              :          contains
     181              : 
     182              : 
     183              :          subroutine check_before_smooth(ierr)
     184              :             integer, intent(out) :: ierr
     185              :             integer :: k, k_old
     186              :             real(dp) :: xq0, xqold_start, xqold_end
     187              : 
     188              :             include 'formats'
     189              :             ierr = 0
     190              :             if (comes_from(1) /= 1 .or. xq_old(1) /= xq_new(1)) then
     191              :                write(*,*) 'mesh plan check_before_smooth: bad value from k=1'
     192              :                ierr = -1
     193              :                return
     194              :             end if
     195              : 
     196              :             do k = 2, nz_new
     197              :                xq0 = xq_new(k)
     198              :                k_old = comes_from(k)
     199              :                xqold_start = xq_old(k_old)
     200              :                if (k_old == nz_old) then
     201              :                   xqold_end = 1d0
     202              :                else
     203              :                   xqold_end = xq_old(k_old+1)
     204              :                end if
     205              :                if (k_old > comes_from(k-1)) then
     206              :                   if (xq0 /= xqold_start) then
     207              :                      write(*,'(A)')
     208              :                      write(*,2) 'nz_new', nz_new
     209              :                      write(*,2) 'k', k
     210              :                      write(*,2) 'comes_from(k-1)', comes_from(k-1)
     211              :                      write(*,2) 'k_old', k_old
     212              :                      write(*,2) 'comes_from(k)', comes_from(k)
     213              :                      write(*,2) 'nz_old', nz_old
     214              :                      write(*,'(A)')
     215              :                      write(*,2) 'xq0', k, xq0
     216              :                      write(*,2) 'xqold_start', k_old, xqold_start
     217              :                      write(*,2) 'xqold_end', k_old, xqold_end
     218              :                      write(*,2) 'xqold_end - xqold_start', k_old, xqold_end - xqold_start
     219              :                      write(*,2) 'xq0 - xqold_start', k_old, xq0 - xqold_start
     220              :                      write(*,'(A)')
     221              :                      write(*,2) 'xq_old(comes_from(k))', k, xq_old(comes_from(k))
     222              :                      write(*,2) 'xq_old(comes_from(k-1))', k, xq_old(comes_from(k-1))
     223              :                      write(*,'(A)')
     224              :                      write(*,*) 'k_old > comes_from(k-1)', k_old > comes_from(k-1)
     225              :                      write(*,*) 'xq0 /= xqold_start', xq0 /= xqold_start
     226              :                      write(*,*) 'mesh plan check_before_smooth'
     227              :                      ierr = -1
     228              :                      return
     229              :                   end if
     230              :                else if (k_old == comes_from(k-1)) then
     231              :                   if (.not. (xq0 > xqold_start .and. xq0 < xqold_end)) then
     232              :                      write(*,'(A)')
     233              :                      write(*,*) '(.not. (xq0 > xqold_start .and. xq0 < xqold_end))', k_old
     234              :                      write(*,2) 'xq_new(k)', k, xq_new(k)
     235              :                      write(*,2) 'xq_old(k_old)', k, xq_old(k_old)
     236              :                      write(*,2) 'xq_old(k_old+1)', k, xq_old(k_old+1)
     237              :                      write(*,2) 'xqold_end', k, xqold_end
     238              :                      write(*,'(A)')
     239              :                      write(*,*) 'k_old == comes_from(k-1)', k_old == comes_from(k-1)
     240              :                      write(*,*) '.not. (xq0 > xqold_start .and. xq0 < xqold_end)', &
     241              :                         .not. (xq0 > xqold_start .and. xq0 < xqold_end)
     242              :                      write(*,*) 'mesh plan check_before_smooth'
     243              :                      ierr = -1
     244              :                      return
     245              :                   end if
     246              :                else
     247              :                   write(*,*) 'comes_from(k) > comes_from(k-1)', k, comes_from(k), comes_from(k-1)
     248              :                   write(*,*) 'mesh plan check_before_smooth'
     249              :                   ierr = -1
     250              :                   return
     251              :                end if
     252              : 
     253              :                cycle  ! use the following for debugging
     254              :                if (dq_new(k-1) < 1d-6*dq_new(k) .or. dq_new(k) < 1d-6*dq_new(k-1)) then
     255              :                   write(*,3) 'bad dq_new ratio', k, nz_new, dq_new(k)/dq_new(k-1), dq_new(k), dq_new(k-1)
     256              :                   write(*,*) 'check_before_smooth'
     257              :                   ierr = -1
     258              :                   return
     259              :                end if
     260              : 
     261              :             end do
     262              : 
     263           10 :          end subroutine check_before_smooth
     264              : 
     265              : 
     266              :          subroutine test_new(ierr)
     267              :             integer, intent(out) :: ierr
     268              :             integer :: k, k_old
     269              :             include 'formats'
     270              :             ierr = 0
     271              :             do k = 1, nz_new
     272              :                if (dq_new(k) <= 0) then
     273              :                   write(*,3) 'bad dq_new'
     274              :                   write(*,2) 'dq_new', k, dq_new(k)
     275              :                   write(*,2) 'dq_new', k-1, dq_new(k-1)
     276              :                   write(*,2) 'xq_new', k, xq_new(k)
     277              :                   write(*,2) 'xq_new', k-1, xq_new(k-1)
     278              :                   write(*,3) 'comes_from', k, comes_from(k)
     279              :                   write(*,3) 'comes_from', k-1, comes_from(k-1)
     280              :                   write(*,2) 'nz_new', nz_new
     281              :                   write(*,2) 'nz_old', nz_old
     282              :                   write(*,2) 'dq_old(comes_from(k))', comes_from(k), dq_old(comes_from(k))
     283              :                   write(*,2) 'dq_old(comes_from(k)-1)', comes_from(k)-1, dq_old(comes_from(k)-1)
     284              :                   write(*,2) 'dq_old(comes_from(k)-2)', comes_from(k)-2, dq_old(comes_from(k)-2)
     285              :                   write(*,2) 'xq_old(comes_from(k))', comes_from(k), xq_old(comes_from(k))
     286              :                   write(*,2) 'xq_old(comes_from(k)-1)', comes_from(k)-1, xq_old(comes_from(k)-1)
     287              :                   write(*,2) 'xq_old(comes_from(k)-2)', comes_from(k)-2, xq_old(comes_from(k)-2)
     288              :                   write(*,*) 'test_new: mesh plan'
     289              :                   ierr = -1
     290              :                   return
     291              :                end if
     292              :                k_old = comes_from(k)
     293              :                if (k_old < 1 .or. k_old > nz_old) then
     294              :                   write(*,*) 'bad value for comes_from', k, k_old
     295              :                   write(*,*) 'test_new: mesh plan'
     296              :                   ierr = -1
     297              :                   return
     298              :                end if
     299              :                if (xq_new(k) < xq_old(k_old)) then
     300              :                   write(*,3) '(xq_new(k) < xq_old(k_old))', k, k_old, &
     301              :                      xq_new(k) - xq_old(k_old), xq_new(k), xq_old(k_old)
     302              :                   write(*,*) 'test_new: mesh plan'
     303              :                   ierr = -1
     304              :                   return
     305              :                end if
     306              :                if (k_old < nz_old) then
     307              :                   if (xq_new(k) > xq_old(k_old+1)) then
     308              :                      write(*,3) '(xq_new(k) > xq_old(k_old+1))', k, k_old+1, &
     309              :                         xq_new(k) - xq_old(k_old+1), xq_new(k), xq_old(k_old+1)
     310              :                      write(*,*) 'test_new: mesh plan'
     311              :                      ierr = -1
     312              :                      return
     313              :                   end if
     314              :                end if
     315              :             end do
     316              :          end subroutine test_new
     317              : 
     318              : 
     319          128 :          subroutine split1(k, ierr)
     320              :             integer, intent(in) :: k
     321              :             integer, intent(out) :: ierr
     322              :             integer :: kk, k_old, k_old_last, split_at_k_old
     323          128 :             real(dp) :: xq_mid, xq_end
     324              :             logical :: from_merger, dbg
     325              : 
     326              :             include 'formats'
     327          128 :             ierr = 0
     328              : 
     329          128 :             k_old = comes_from(k)
     330          128 :             k_old_last = -1
     331          128 :             xq_end = -1
     332          128 :             from_merger = (xq_new(k) == xq_old(k_old) .and. dq_new(k) > dq_old(k_old) + min_dq*1d-3)
     333              : 
     334          128 :             dbg = (k_old == -1)
     335              : 
     336          128 :             if (dbg) then
     337            0 :                write(*,2) 'start split1 k', k
     338            0 :                write(*,2) 'nz_old', nz_old
     339            0 :                write(*,2) 'nz_new', nz_new
     340            0 :                do kk=1400,nz_new
     341            0 :                   if (dq_new(kk) < 1d-12) then
     342            0 :                      write(*,2) 'dq_new(kk)', kk, dq_new(kk)
     343            0 :                      call mesa_error(__FILE__,__LINE__,'debug: split1')
     344              :                   end if
     345              :                end do
     346            0 :                do kk = 2, nz_new
     347            0 :                   if (dq_new(kk-1) < 1d-6*dq_new(kk) .or. dq_new(kk) < 1d-6*dq_new(kk-1)) then
     348            0 :                      write(*,3) 'bad dq_new ratio', kk, nz_new, dq_new(kk), dq_new(kk-1)
     349            0 :                      call mesa_error(__FILE__,__LINE__,'debug: split1')
     350              :                   end if
     351              :                end do
     352              :             end if
     353              : 
     354          128 :             if (from_merger) then  ! find range of old cells that were merged to form k
     355          128 :                if (k == nz_new) then
     356            0 :                   xq_end = 1
     357            0 :                   k_old_last = nz_old
     358              :                else
     359          128 :                   xq_end = xq_new(k+1)
     360          128 :                   k_old_last = 0
     361          256 :                   do kk = k_old+1, nz_old  ! find last old cell included in k
     362          256 :                      if (xq_old(kk) == xq_end) then
     363          128 :                         k_old_last = kk-1; exit
     364              :                      end if
     365          128 :                      if (xq_old(kk) > xq_end) then
     366            0 :                         write(*,*) 'oops'
     367            0 :                         write(*,2) 'xq_old(kk)', kk, xq_old(kk)
     368            0 :                         write(*,2) 'xq_old(kk-1)', kk-1, xq_old(kk-1)
     369            0 :                         write(*,2) 'xq_end', k, xq_end
     370            0 :                         write(*,*) 'split1'
     371            0 :                         ierr = -1
     372            0 :                         return
     373              :                      end if
     374              :                   end do
     375          128 :                   if (k_old_last == k_old) then
     376              :                      from_merger = .false.
     377          128 :                   else if (k_old_last < k_old) then
     378            0 :                      write(*,*) 'confusion in split1 for k_old_last'
     379            0 :                      write(*,2) 'k_old', k_old
     380            0 :                      write(*,2) 'k_old_last', k_old_last
     381            0 :                      write(*,2) 'nz_old', nz_old
     382            0 :                      write(*,2) 'k', k
     383            0 :                      write(*,2) 'nz_new', nz_new
     384            0 :                      write(*,'(A)')
     385            0 :                      write(*,2) 'dq_new(k)', k, dq_new(k)
     386            0 :                      write(*,2) 'dq_old(k_old)', k_old, dq_old(k_old)
     387            0 :                      write(*,2) 'dq_new(k)-dq_old(k_old)', k_old, dq_new(k)-dq_old(k_old)
     388            0 :                      write(*,'(A)')
     389            0 :                      write(*,2) 'xq_new(k)', k, xq_new(k)
     390            0 :                      write(*,2) 'xq_new(k)+dq_new(k)', k, xq_new(k)+dq_new(k)
     391            0 :                      write(*,2) 'xq_end', k, xq_end
     392            0 :                      write(*,*) 'split1'
     393            0 :                      ierr = -1
     394            0 :                      return
     395              :                   end if
     396              :                end if
     397              :             end if
     398              : 
     399          128 :             if (nz_new == new_capacity) then  ! increase allocated size
     400            0 :                new_capacity = (new_capacity*5)/4 + 10
     401            0 :                call realloc(s, nz_new, new_capacity, xq_new, dq_new, which_gval, comes_from, ierr)
     402            0 :                if (ierr /= 0) return
     403              :             end if
     404          128 :             nz_new = nz_new + 1
     405          128 :             if (max_allowed_nz > 0 .and. nz_new > max_allowed_nz) then
     406            0 :                write(*,*) 'tried to increase number of mesh points beyond max allowed nz', max_allowed_nz
     407            0 :                ierr = -1
     408            0 :                return
     409              :             end if
     410        17004 :             do kk = nz_new, k+1, -1
     411        16876 :                xq_new(kk) = xq_new(kk-1)
     412        16876 :                dq_new(kk) = dq_new(kk-1)
     413        16876 :                which_gval(kk) = which_gval(kk-1)
     414        17004 :                comes_from(kk) = comes_from(kk-1)
     415              :             end do
     416              : 
     417          128 :             if (from_merger) then  ! split by breaking up the merger
     418          128 :                xq_mid = xq_new(k) + dq_new(k)*0.5d0
     419          128 :                split_at_k_old = k_old_last
     420          146 :                do kk = k_old+1, k_old_last  ! check interior boundaries for closest to xq_mid
     421          146 :                   if (xq_old(kk) >= xq_mid) then
     422          110 :                      if (xq_old(kk) - xq_mid < xq_mid - xq_old(kk-1)) then  ! xq_mid closer to xq_old(kk)
     423              :                         split_at_k_old = kk
     424              :                      else  ! xq_mid closer to xq_old(kk-1)
     425            0 :                         split_at_k_old = kk-1
     426              :                      end if
     427              :                      exit
     428              :                   end if
     429              :                end do
     430          128 :                comes_from(k+1) = split_at_k_old
     431          128 :                xq_new(k+1) = xq_old(split_at_k_old)
     432          256 :                dq_new(k) = sum(dq_old(k_old:split_at_k_old-1))
     433          256 :                dq_new(k+1) = sum(dq_old(split_at_k_old:k_old_last))
     434              :             else
     435            0 :                dq_new(k:k+1) = dq_new(k)*0.5d0
     436            0 :                xq_new(k+1) = xq_new(k) + dq_new(k)
     437              :                ! fix up comes_from(k+1)
     438            0 :                comes_from(k+1) = nz_old  ! just in case
     439            0 :                do k_old = comes_from(k), nz_old-1
     440            0 :                   if (xq_new(k+1) <= xq_old(k_old+1)) then
     441            0 :                      comes_from(k+1) = k_old
     442            0 :                      exit
     443              :                   end if
     444              :                end do
     445              :             end if
     446              : 
     447          128 :             if (dbg) then
     448            0 :                write(*,2) 'split1 dq_new k', k, dq_new(k)
     449            0 :                write(*,2) 'split1 dq_new k+1', k+1, dq_new(k+1)
     450            0 :                write(*,2) 'comes_from', k_old
     451            0 :                write(*,2) 'nz_old', nz_old
     452            0 :                write(*,2) 'nz_new', nz_new
     453            0 :                do kk=1400,nz_new
     454            0 :                   if (dq_new(kk) < 1d-12) then
     455            0 :                      write(*,2) 'dq_new(kk)', kk, dq_new(kk)
     456            0 :                      call mesa_error(__FILE__,__LINE__,'debug: split1')
     457              :                   end if
     458              :                end do
     459              :             end if
     460              : 
     461              :          end subroutine split1
     462              : 
     463              : 
     464        31907 :          logical function okay_to_split1(k_old, dq_new, remaining_dq_old)
     465              :             integer, intent(in) :: k_old
     466              :             real(dp), intent(in) :: dq_new, remaining_dq_old
     467        31907 :             real(dp) :: dr_old, min_dr, rR, rL, dlnR_new
     468              :             logical :: dbg
     469              : 
     470              :             include 'formats'
     471              : 
     472        31907 :             dbg = .false.
     473        31907 :             okay_to_split1 = .false.
     474        31907 :             if (do_not_split(k_old)) return
     475              : 
     476        31907 :             if (max(dq_new,remaining_dq_old) < max(min_dq_for_split,2*min_dq)) return
     477              : 
     478              :             if (dbg) then
     479              :                write(*,2) 'remaining_dq_old', k_old, remaining_dq_old
     480              :                write(*,1) 'dq_new', dq_new
     481              :                write(*,1) 'min_dq_for_split', min_dq_for_split
     482              :                write(*,1) 'min_dq', min_dq
     483              :                write(*,'(A)')
     484              :             end if
     485              : 
     486        31907 :             if (0d0 < remaining_dq_old .and. dq_new > 0.99d0*remaining_dq_old) then
     487              :                if (dbg) then
     488              :                   write(*,2) 'dq_old', k_old, remaining_dq_old
     489              :                   write(*,1) 'dq_new', dq_new
     490              :                   write(*,1) 'dq_new/remaining_dq_old', dq_new/remaining_dq_old
     491              :                   write(*,'(A)')
     492              :                end if
     493              :                return
     494              :             end if
     495              : 
     496        31907 :             if (k_old < nz_old) then
     497              : 
     498        31907 :                rR = s% r(k_old)
     499        31907 :                rL = s% r(k_old+1)
     500        31907 :                dr_old = rR - rL
     501        31907 :                min_dr = s% csound(k_old)*s% mesh_min_dr_div_cs
     502        31907 :                if (dr_old*dq_new/dq_old(k_old) < 2*min_dr) then
     503              :                   return  ! sound crossing time would be too small
     504              :                end if
     505              : 
     506        31907 :                min_dr = s% mesh_min_dr_div_dRstar*(s% r(1) - s% R_center)
     507        31907 :                if (dr_old*dq_new/dq_old(k_old) < 2*min_dr) then
     508              :                   return  ! new dr would be too small
     509              :                end if
     510              : 
     511        31907 :                if (s% mesh_min_dlnR > 0d0) then
     512        31907 :                   dlnR_new = log((rL + dr_old*dq_new/dq_old(k_old))/rL)
     513        31907 :                   if (dlnR_new < 2*s% mesh_min_dlnR) then
     514              :                      ! the factor of 2 is a safety margin.
     515              :                      return
     516              :                   end if
     517              :                end if
     518              : 
     519              :             end if
     520        31907 :             okay_to_split1 = .true.
     521              : 
     522              :          end function okay_to_split1
     523              : 
     524              : 
     525           10 :          subroutine smooth_new_points(ierr)
     526              :             integer, intent(out) :: ierr
     527              : 
     528              :             logical :: dbg, done
     529              :             integer :: k, k_old
     530           10 :             real(dp) :: alfa
     531              : 
     532              :             include 'formats'
     533              : 
     534           10 :             ierr = 0
     535           10 :             dbg = .false.
     536           10 :             alfa = mesh_max_allowed_ratio
     537              : 
     538              :             do  ! repeat until nothing left to do
     539              :                if (min_k_old_for_split <= 1 .and. &
     540           20 :                      dq_new(1) > alfa*dq_new(2) .and. &
     541              :                      okay_to_split1(1,dq_new(1),0d0)) then
     542            0 :                   call split1(1,ierr)
     543            0 :                   if (ierr /= 0) return
     544              :                   cycle
     545              :                end if
     546           20 :                done = .true.
     547           20 :                k = 2
     548              :                do  ! check for cell that is too large
     549        21294 :                   if (k == nz_new) exit
     550        21274 :                   k_old = comes_from(k)
     551              :                   if (k_old <= max_k_old_for_split .and. &
     552              :                       k_old >= min_k_old_for_split .and. &
     553        21274 :                       okay_to_split1(k_old,dq_new(k),0d0) .and. &
     554              :                         (dq_new(k) > max_dq .or. &
     555              :                            dq_new(k) > alfa*dq_new(k+1) .or. &
     556           20 :                            dq_new(k) > alfa*dq_new(k-1))) then
     557           98 :                      call split1(k,ierr)
     558           98 :                      if (ierr /= 0) return
     559              :                      done = .false.
     560              :                      ! don't increment k; want to recheck the cell in case need to split again
     561              :                   else
     562        21176 :                      k = k + 1
     563              :                   end if
     564              :                end do
     565              : 
     566              :                if (dbg) then
     567              :                   call test_new(ierr)
     568              :                   if (ierr /= 0) call mesa_error(__FILE__,__LINE__,'debug: mesh_plan, smooth_new_points')
     569              :                end if
     570              : 
     571           20 :                if (done) exit
     572              : 
     573              :                ! now go in opposite direction
     574           10 :                done = .true.
     575           10 :                k = nz_new-1
     576              :                do
     577        10643 :                   if (k == 1) exit
     578        10633 :                   if (okay_to_split1(comes_from(k),dq_new(k),0d0) .and. &
     579           10 :                         (dq_new(k) > alfa*dq_new(k+1) .or. dq_new(k) > alfa*dq_new(k-1))) then
     580           30 :                      call split1(k,ierr)
     581           30 :                      if (ierr /= 0) return
     582           30 :                      done = .false.
     583           30 :                      k = k + 1  ! recheck the same cell
     584              :                   else
     585        10603 :                      k = k - 1
     586              :                   end if
     587              :                end do
     588              : 
     589              :                if (dbg) then
     590              :                   call test_new(ierr)
     591              :                   if (ierr /= 0) call mesa_error(__FILE__,__LINE__,'debug: mesh_plan, smooth_new_points')
     592              :                end if
     593              : 
     594           20 :                if (done) exit
     595              : 
     596              :             end do
     597              : 
     598              :          end subroutine smooth_new_points
     599              : 
     600              : 
     601           10 :          subroutine pick_new_points(s, ierr)
     602              :             type (star_info), pointer :: s
     603              :             integer, intent(out) :: ierr
     604              : 
     605              :             logical :: dbg, force_merge_with_one_more
     606           10 :             real(dp) :: maxval_delta_xa, next_dq_max, beta_limit, &
     607           10 :                remaining_dq_old, min_dr
     608              :             integer :: kk, k_old_init, k_old_next, k_old_next_max, j00, jm1, i, max_merge
     609              : 
     610              :             include 'formats'
     611              : 
     612           10 :             beta_limit = 0.1d0
     613              : 
     614           10 :             ierr = 0
     615           10 :             k_old = 1
     616           10 :             k_new = 1
     617           10 :             xq_new(1) = 0
     618           10 :             min_dr = s% mesh_min_dr_div_dRstar*(s% r(1) - s% R_center)
     619              : 
     620              :             do  ! pick next point location
     621              : 
     622        10495 :                dbg = plan_dbg .or. (k_new == kdbg)  !.or. (s% mesh_call_number == 2005)
     623              : 
     624              :                ! when reach this point,
     625              :                ! have set xq_new(k) for k = 1 to k_new, and dq_new(k) for k = 1 to k_new-1.
     626              :                ! and have finished using old points from 1 to k_old
     627              :                ! i.e., xq_old(k_old+1) > xq_new(k_new) >= xq_old(k_old)
     628              : 
     629        10495 :                k_old_init = k_old
     630              : 
     631        10495 :                if (k_new == 1) then
     632           10 :                   next_dq_max = max_surface_cell_dq
     633              :                else
     634        10485 :                   next_dq_max = dq_new(k_new-1)*mesh_max_allowed_ratio
     635              :                end if
     636              : 
     637              :                ! make initial choice based on gradients. may reduce later.
     638        10495 :                if (dbg) then
     639            0 :                   write(*,'(A)')
     640            0 :                   write(*,3) 'call pick_next_dq', k_old, k_new, next_dq_max
     641              :                end if
     642              : 
     643        10495 :                if (s% gradr(k_old) > s% grada(k_old) .and. &
     644              :                      s% min_dq_for_xa_convective > 0d0) then
     645         1325 :                   min_dq_for_xa = s% min_dq_for_xa_convective
     646              :                else
     647         9170 :                   min_dq_for_xa = s% min_dq_for_xa
     648              :                end if
     649              : 
     650        10495 :                min_dq_for_logT = s% min_dq_for_logT
     651              : 
     652              :                next_dq = pick_next_dq(s, &
     653              :                   dbg, next_dq_max, k_old, k_new, nz_old, num_gvals, &
     654              :                   xq_new, dq_new, xq_old, dq_old, min_dq, min_dq_for_split, &
     655              :                   min_dq_for_xa, min_dq_for_logT, &
     656              :                   max_surface_cell_dq, max_dq_cntr, max_num_subcells, &
     657              :                   gval_is_xa_function, gval_is_logT_function, gvals, &
     658        10495 :                   delta_gval_max, gval_names, which_gval, ierr)
     659        10495 :                if (ierr /= 0) return
     660              : 
     661        10495 :                if (dbg) &
     662            0 :                   write(*,3) 'pick_next_dq next_dq prev_dq', k_old, k_new, next_dq, dq_old(k_old)
     663              : 
     664        10495 :                if (k_new == 1) then
     665           10 :                   max_merge = max_num_merge_surface_cells
     666              :                else
     667        10485 :                   max_merge = max_num_merge_cells
     668              :                end if
     669              : 
     670        10495 :                if (k_old < nz_old) then
     671        10485 :                   remaining_dq_old = xq_old(k_old+1)-xq_new(k_new)
     672              :                else
     673           10 :                   remaining_dq_old = 1d0-xq_new(k_new)
     674              :                end if
     675              : 
     676        10495 :                if (next_dq < remaining_dq_old) then
     677            0 :                   if (.not. okay_to_split1(k_old, next_dq, remaining_dq_old)) then
     678            0 :                      next_dq = remaining_dq_old  ! dq_old(k_old)
     679              :                   end if
     680              :                end if
     681              : 
     682        10495 :                if (next_dq > max_dq) then
     683           21 :                   if (xq_new(k_new) == xq_old(k_old)) then
     684         2623 :                      do i = nz_old, k_old+1, -1
     685         2623 :                         if (xq_old(i) - xq_new(k_new) <= max_dq) then
     686           21 :                            next_dq = xq_old(i) - xq_new(k_new)
     687           21 :                            exit
     688              :                         end if
     689              :                      end do
     690              :                   end if
     691              :                end if
     692              : 
     693        10495 :                if (next_dq > max_dq) then
     694            0 :                   next_dq = xq_old(k_old) + dq_old(k_old) - xq_new(k_new)
     695              :                end if
     696              : 
     697        10495 :                if (k_new == 1 .and. next_dq > max_surface_cell_dq) then
     698            0 :                   if (k_old_init == -1 .and. .true.) write(*,*) 'next_dq > max_surface_cell_dq'
     699            0 :                   next_dq = max_surface_cell_dq
     700              :                end if
     701              : 
     702        10495 :                next_xq = xq_new(k_new) + next_dq
     703        10495 :                if (next_xq > 1 - min_dq) then
     704           10 :                   next_xq = (1 + xq_new(k_new))/2
     705           10 :                   if (k_old < nz_old) then  ! make sure don't split current k_old for this case
     706            0 :                      if (xq_old(k_old+1) > next_xq) next_xq = xq_old(k_old+1)
     707              :                   end if
     708           10 :                   next_dq = next_xq - xq_new(k_new)
     709              :                end if
     710              : 
     711        10495 :                if (k_old < nz_old) then
     712              : 
     713        10485 :                   if (xq_new(k_new) == xq_old(k_old) .and. &
     714              :                         next_dq > dq_old(k_old) - min_dq/2) then
     715              : 
     716        10485 :                      if (.not. okay_to_merge) then
     717              : 
     718            0 :                         k_old_next = k_old + 1
     719              : 
     720        10485 :                      else if (k_old < min_k_old_for_split .or. &
     721              :                               k_old > max_k_old_for_split) then
     722              : 
     723            0 :                         k_old_next = k_old + 1
     724              : 
     725              :                      else  ! consider doing merge
     726              : 
     727        10485 :                         if (next_dq > 1.5d0*dq_old(k_old)) then
     728         7240 :                            next_dq = 0.9d0*next_dq  ! to avoid split-merge flip-flops
     729         7240 :                            next_xq = xq_new(k_new) + next_dq
     730              :                         end if
     731              : 
     732        10485 :                         k_old_next_max = min(nz_old, k_old + max_merge)
     733        10485 :                         k_old_next = k_old_next_max  ! will cut this back as necessary
     734        22526 :                         do kk=k_old+1,k_old_next_max
     735       209260 :                            maxval_delta_xa = maxval(abs(s% xa(:,kk)-s% xa(:,kk-1)))
     736       188334 :                            j00 = maxloc(s% xa(:,kk),dim=1)
     737       188334 :                            jm1 = maxloc(s% xa(:,kk-1),dim=1)
     738              :                            if (maxval_delta_xa > s% max_delta_x_for_merge .or. &
     739        20926 :                                j00 /= jm1 .or. is_convective_boundary(kk) .or. &
     740         1600 :                                is_crystal_boundary(kk)) then
     741              :                               ! don't merge across convective or crystal boundary
     742           58 :                               k_old_next = kk-1
     743           58 :                               exit
     744        20868 :                            else if (next_xq <= xq_old(kk) + min_dq/2) then
     745         8827 :                               k_old_next = max(k_old+1,kk-1)
     746         8827 :                               exit
     747              :                            end if
     748              :                         end do
     749              : 
     750              :                      end if
     751              : 
     752        10485 :                      k_old_next = max(k_old_next, k_old+1)
     753        10485 :                      next_xq = xq_old(k_old_next)
     754        10485 :                      next_dq = next_xq - xq_new(k_new)
     755              : 
     756            0 :                   else if (next_xq >= xq_old(k_old+1) - min_dq/2) then
     757              :                      ! this is final subcell of a split, so adjust to finish the parent cell
     758              : 
     759            0 :                      k_old_next = k_old+1
     760            0 :                      next_xq = xq_old(k_old_next)
     761            0 :                      next_dq = next_xq - xq_new(k_new)
     762              : 
     763              :                   else  ! non-final subcell of split
     764              : 
     765            0 :                      k_old_next = k_old
     766              : 
     767              :                   end if
     768              : 
     769        10485 :                   if (next_xq == xq_old(k_old_next)) then
     770              :                      ! finishing 1 or more old cells and not already at max merge.
     771              :                      ! consider forcing a merge with the next cell to make this one larger.
     772        10485 :                      force_merge_with_one_more = .false.
     773              : 
     774        10485 :                      if (dq_old(k_old) < min_dq) then
     775              :                         force_merge_with_one_more = .true.
     776        10485 :                      else if (s% merge_if_dlnR_too_small) then
     777            0 :                         if (xq_new(k_new) <= xq_old(k_old) .and. &
     778              :                             s% lnR(k_old) - s% lnR(k_old_next) < s% mesh_min_dlnR) then
     779              :                            force_merge_with_one_more = .true.
     780            0 :                         else if (k_old_next == nz_old .and. s% R_center > 0) then
     781            0 :                            force_merge_with_one_more = s% lnR(k_old_next) - log(s% R_center) < s% mesh_min_dlnR
     782              :                         end if
     783              :                      end if
     784              : 
     785        10485 :                      if ((.not. force_merge_with_one_more) .and. s% merge_if_dr_div_cs_too_small) then
     786        10485 :                         if (xq_new(k_new) <= xq_old(k_old) .and. &
     787              :                             s% r(k_old) - s% r(k_old_next) < s% mesh_min_dr_div_cs*s% csound(k_old)) then
     788              :                            force_merge_with_one_more = .true.
     789        10485 :                         else if (k_old_next == nz_old) then
     790              :                            force_merge_with_one_more = (s% r(k_old_next) - s% R_center) < &
     791           10 :                                        s% mesh_min_dr_div_cs*s% csound(k_old_next)
     792           10 :                            if (force_merge_with_one_more .and. dbg) &
     793            0 :                               write(*,3) 'do merge for k_old_next == nz_old', k_old, k_old_next, &
     794            0 :                                  s% r(k_old) - s% R_center, &
     795            0 :                                  s% mesh_min_dr_div_cs*s% csound(k_old_next), &
     796            0 :                                  s% mesh_min_dr_div_cs, s% csound(k_old_next)
     797              :                         end if
     798              :                      end if
     799              : 
     800        10485 :                      if ((.not. force_merge_with_one_more) .and. &
     801              :                            s% merge_if_dr_div_dRstar_too_small) then
     802        10485 :                         if (xq_new(k_new) <= xq_old(k_old) .and. &
     803              :                             s% r(k_old) - s% r(k_old_next) < min_dr) then
     804              :                            force_merge_with_one_more = .true.
     805        10485 :                         else if (k_old_next == nz_old) then
     806           10 :                            force_merge_with_one_more = (s% r(k_old_next) - s% R_center) < min_dr
     807           10 :                            if (force_merge_with_one_more .and. dbg) &
     808            0 :                               write(*,3) 'do merge for k_old_next == nz_old', k_old, k_old_next, &
     809            0 :                                  s% r(k_old) - s% R_center, min_dr
     810              :                         end if
     811              :                      end if
     812              : 
     813        10485 :                      if (force_merge_with_one_more) then
     814            0 :                         k_old_next = k_old_next + 1
     815            0 :                         if (k_old_next < nz_old) then
     816            0 :                            next_xq = xq_old(k_old_next)
     817              :                         else
     818            0 :                            next_xq = 1d0
     819              :                         end if
     820            0 :                         next_dq = next_xq - xq_new(k_new)
     821            0 :                         if (dbg) then
     822            0 :                            write(*,3) 'force merge', k_old, k_new, next_xq, next_dq
     823            0 :                            write(*,'(A)')
     824              :                         end if
     825              :                      end if
     826              : 
     827              :                   end if
     828              : 
     829        10485 :                   k_old = k_old_next
     830              : 
     831              :                end if
     832              : 
     833        10495 :                comes_from(k_new) = k_old_init
     834              : 
     835              :                ! check if we're done
     836        10495 :                if (1 - xq_new(k_new) < max_dq_cntr .or. 1 - next_xq < min_dq) then
     837           10 :                   dq_new(k_new) = 1 - xq_new(k_new)
     838              :                   exit
     839              :                end if
     840              : 
     841        10485 :                dq_new(k_new) = next_dq
     842              : 
     843        10485 :                if (k_new == new_capacity) then  ! increase allocated size
     844            0 :                   new_capacity = (new_capacity*5)/4 + 10
     845            0 :                   call realloc(s, k_new, new_capacity, xq_new, dq_new, which_gval, comes_from, ierr)
     846            0 :                   if (ierr /= 0) return
     847              :                end if
     848              : 
     849        10485 :                if (next_xq < xq_new(k_new)) then
     850            0 :                   write(*,*) 'nz_old', nz_old
     851            0 :                   write(*,*) 'k_new', k_new
     852            0 :                   write(*,1) 'next_xq', next_xq
     853            0 :                   write(*,1) 'xq_new(k_new)', xq_new(k_new)
     854            0 :                   write(*,*) 'pick_new_points: next_xq < xq_new(k_new)'
     855            0 :                   ierr = -1
     856            0 :                   return
     857              :                end if
     858              : 
     859      5656552 :                dq_sum = sum(dq_new(1:k_new))
     860              : 
     861        10485 :                k_new = k_new + 1
     862        10485 :                if (max_allowed_nz > 0 .and. k_new > max_allowed_nz) then
     863            0 :                   write(*,*) 'tried to increase number of mesh points beyond max allowed nz', max_allowed_nz
     864            0 :                   ierr = -1
     865            0 :                   return
     866              :                end if
     867              : 
     868        10485 :                xq_new(k_new) = next_xq
     869        10485 :                if (abs(xq_new(k_new) - dq_sum) > 1d-6) then
     870            0 :                   write(*,'(A)')
     871            0 :                   write(*,*) 'k_new', k_new
     872            0 :                   write(*,1) 'xq_new(k_new) - dq_sum', xq_new(k_new) - dq_sum
     873            0 :                   write(*,1) 'xq_new(k_new)', xq_new(k_new)
     874            0 :                   write(*,1) 'dq_sum', dq_sum
     875            0 :                   write(*,*) 'pick_new_points: abs(xq_new(k_new) - dq_sum) > 1d-6'
     876            0 :                   ierr = -1
     877            0 :                   return
     878              :                end if
     879              :                !write(*,2) 'xq_new(k_new) - dq_sum', k_new, xq_new(k_new) - dq_sum
     880              : 
     881              :                ! increment k_old if necessary
     882        10485 :                do while (k_old < nz_old)
     883        10475 :                   if (xq_old(k_old+1) > next_xq) exit
     884        10485 :                   k_old = k_old + 1
     885              :                end do
     886              : 
     887              :             end do
     888              : 
     889           10 :             nz_new = k_new
     890              : 
     891              :             if (plan_dbg) write(*,2) 'after pick_new_points: nz_new', nz_new
     892              : 
     893              :          end subroutine pick_new_points
     894              : 
     895              : 
     896        20926 :          logical function is_convective_boundary(kk)
     897              :             integer, intent(in) :: kk
     898        20926 :             is_convective_boundary = .false.
     899        20926 :             if (kk == nz) return
     900              :             is_convective_boundary = &
     901              :                (s% mixing_type(kk) == convective_mixing .and. &
     902              :                 s% mixing_type(kk+1) /= convective_mixing) .or. &
     903              :                (s% mixing_type(kk+1) == convective_mixing .and. &
     904        20916 :                 s% mixing_type(kk) /= convective_mixing)
     905              :          end function is_convective_boundary
     906              : 
     907        20868 :          logical function is_crystal_boundary(kk)
     908              :             integer, intent(in) :: kk
     909              :             if(s% do_phase_separation .and. &  ! only need this protection when phase separation is on
     910        20868 :                  s% m(kk) <= s% crystal_core_boundary_mass .and. &
     911              :                  s% m(kk-1) >= s% crystal_core_boundary_mass) then
     912              :                is_crystal_boundary = .true.
     913              :             else
     914        20868 :                is_crystal_boundary = .false.
     915              :             end if
     916        20868 :          end function is_crystal_boundary
     917              : 
     918              :          subroutine open_debug_file
     919              :             include 'formats'
     920              :             open(newunit=iounit, file=trim('plan_debug.data'), action='write', iostat=ierr)
     921              :             if (ierr /= 0) then
     922              :                write(*, *) 'open plan_debug.data failed'
     923              :                call mesa_error(__FILE__,__LINE__,'debug do_mesh_plan')
     924              :             end if
     925              :             write(*,*) 'write plan_debug.data'
     926              :          end subroutine open_debug_file
     927              : 
     928              : 
     929              :       end subroutine do_mesh_plan
     930              : 
     931              : 
     932            0 :       subroutine realloc(s, old_size, new_capacity, xq_new, dq_new, which_gval, comes_from, ierr)
     933              :          use alloc
     934              :          type (star_info), pointer :: s
     935              :          integer, intent(in) :: old_size, new_capacity
     936              :          real(dp), pointer :: xq_new(:), dq_new(:)
     937              :          integer, pointer :: which_gval(:), comes_from(:)
     938              :          integer, intent(out) :: ierr
     939              :          integer, parameter :: extra = 100
     940            0 :          call realloc_integer_work_array(s, which_gval, old_size, new_capacity, extra, ierr)
     941            0 :          if (ierr /= 0) return
     942            0 :          call realloc_integer_work_array(s, comes_from, old_size, new_capacity, extra, ierr)
     943            0 :          if (ierr /= 0) return
     944            0 :          call realloc_work_array(s, .false., xq_new, old_size, new_capacity, extra, 'mesh_plan', ierr)
     945            0 :          if (ierr /= 0) return
     946            0 :          call realloc_work_array(s, .false., dq_new, old_size, new_capacity, extra, 'mesh_plan', ierr)
     947            0 :          if (ierr /= 0) return
     948            0 :       end subroutine realloc
     949              : 
     950              : 
     951        10495 :       real(dp) function pick_next_dq(s, &
     952              :             dbg, next_dq_max, k_old, k_new, nz_old, num_gvals, xq_new, dq_new, &
     953              :             xq_old, dq_old, min_dq, min_dq_for_split, min_dq_for_xa, min_dq_for_logT, &
     954              :             max_surface_cell_dq, max_dq_cntr, max_num_subcells, &
     955              :             gval_is_xa_function, gval_is_logT_function, gvals, delta_gval_max, &
     956        10495 :             gval_names, which_gval, ierr)
     957            0 :          use mesh_functions, only: max_allowed_gvals
     958              :          type (star_info), pointer :: s
     959              :          logical, intent(in) :: dbg
     960              :          integer, intent(in) :: k_old, k_new, nz_old, num_gvals, max_num_subcells
     961              :          real(dp), pointer :: xq_new(:), dq_new(:)  ! (nz)
     962              :          real(dp), pointer :: xq_old(:)  ! (nz_old)
     963              :          real(dp), pointer :: dq_old(:)  ! (nz_old)
     964              :          logical, dimension(max_allowed_gvals) :: gval_is_xa_function, gval_is_logT_function
     965              :          real(dp), pointer :: gvals(:,:)  ! (nz_old, num_gvals)
     966              :          real(dp), intent(in) :: &
     967              :             next_dq_max, min_dq, min_dq_for_split, &
     968              :             min_dq_for_xa, min_dq_for_logT, max_surface_cell_dq, max_dq_cntr
     969              :          real(dp), pointer :: delta_gval_max(:)  ! (nz_old, num_gvals)
     970              :          character (len=32) :: gval_names(:)  ! (num_gvals)  for debugging.
     971              :          integer, pointer :: which_gval(:)  ! (nz_new)  for debugging.
     972              :          integer, intent(out) :: ierr
     973              : 
     974        41980 :          real(dp) :: nxt_dqs(num_gvals), default
     975              :          integer :: i, j, jmin, op_err
     976              :          logical :: pkdbg
     977              : 
     978              :          include 'formats'
     979              : 
     980        10495 :          pkdbg = dbg  !.or. k_old == 4000
     981        10495 :          ierr = 0
     982              : 
     983        10495 :          if (pkdbg) write(*,*)
     984            0 :          if (pkdbg) write(*,2) 'dq_old(k_old)', k_old, dq_old(k_old)
     985              : 
     986        10495 :          if (k_new == 1) then
     987           10 :             pick_next_dq = min(1d0, sqrt(min_dq))
     988        10485 :          else if (k_new <= 20) then
     989          190 :             pick_next_dq = min(1-xq_new(k_new), 10*dq_new(k_new-1))
     990              :          else
     991        10295 :             pick_next_dq = 1-xq_new(k_new)
     992              :          end if
     993              : 
     994        41980 :          nxt_dqs(:) = pick_next_dq
     995        10495 :          if (k_old == nz_old) then
     996           10 :             which_gval(k_new) = 0
     997           10 :             pick_next_dq = max(min_dq, (1-xq_new(k_new)) - max_dq_cntr)
     998           10 :             do i=1,10
     999           10 :                if (1-xq_new(k_new) <= max_dq_cntr*i) then
    1000           10 :                   pick_next_dq = (1-xq_new(k_new))/i
    1001           10 :                   exit
    1002              :                end if
    1003              :             end do
    1004           10 :             return
    1005              :          end if
    1006              : 
    1007        10485 :          default = pick_next_dq  ! default size. can be reduced according to gradients of gvals
    1008        41940 :          do j=1,num_gvals
    1009              :             nxt_dqs(j) = pick1_dq(s, &
    1010              :                j, next_dq_max, default, .false., k_old, k_new, nz_old, &
    1011              :                xq_new, xq_old, dq_old, min_dq, min_dq_for_xa, min_dq_for_logT, max_num_subcells, &
    1012              :                gval_is_xa_function(j), gval_is_logT_function(j), &
    1013        31455 :                gvals, delta_gval_max, gval_names, op_err)
    1014        41940 :             if (op_err /= 0) ierr = op_err
    1015              :          end do
    1016              : 
    1017        52425 :          jmin = minloc(nxt_dqs(:),dim=1)
    1018        10485 :          if (pkdbg) write(*,3) 'jmin, k_new, init pick_next_dq', jmin, k_new, pick_next_dq
    1019        10485 :          which_gval(k_new) = jmin
    1020        10485 :          pick_next_dq = max(min_dq, min(pick_next_dq, nxt_dqs(jmin)))
    1021              : 
    1022        10495 :       end function pick_next_dq
    1023              : 
    1024              : 
    1025        31455 :       real(dp) function pick1_dq(s, &
    1026              :             j, next_dq_max, default, dbg, k_old, k_new, nz_old, &
    1027              :             xq_new, xq_old, dq_old, min_dq, min_dq_for_xa, min_dq_for_logT, max_num_subcells, &
    1028        31455 :             is_xa_function, is_logT_function, gvals, delta_gval_max, gval_names, ierr)
    1029        10495 :          use num_lib, only: binary_search
    1030              :          type (star_info), pointer :: s
    1031              :          integer, intent(in) :: j
    1032              :          real(dp), intent(in) :: next_dq_max, default, min_dq, min_dq_for_xa, min_dq_for_logT
    1033              :          logical, intent(in) :: dbg
    1034              :          integer, intent(in) :: k_old, k_new, nz_old, max_num_subcells
    1035              :          real(dp), pointer :: xq_new(:)  ! (nz)
    1036              :          real(dp), pointer :: xq_old(:)  ! (nz_old)
    1037              :          real(dp), pointer :: dq_old(:)  ! (nz_old)
    1038              :          logical :: is_xa_function, is_logT_function
    1039              :          real(dp), pointer :: gvals(:,:)  ! (nz_old, num_gvals)
    1040              :          real(dp), pointer :: delta_gval_max(:)  ! (nz_old, num_gvals)
    1041              :          character (len=32) :: gval_names(:)  ! (num_gvals)  for debugging.
    1042              :          integer, intent(out) :: ierr
    1043              : 
    1044        31455 :          real(dp) :: gnew, dgnew, gmax, gmin, xq, dq_next, dq_sum, sz, dval
    1045              :          integer :: k
    1046              :          logical :: dbg1
    1047              : 
    1048              :          include 'formats'
    1049              : 
    1050        31455 :          ierr = 0
    1051        31455 :          dbg1 = dbg  !.or. (k_old == -1)
    1052              : 
    1053        31455 :          pick1_dq = default
    1054        31455 :          dq_next = -1
    1055              : 
    1056        31455 :          if (dbg1) write(*,*)
    1057            0 :          if (dbg1) write(*,*) 'find max allowed dq for gvals(:,j)', j
    1058              :          ! find max allowed dq for gvals(:,j)
    1059              : 
    1060              :          ! linear interpolate to estimate gvals(:,j) at q_new(k_new)
    1061        31455 :          dval = gvals(k_old,j) - gvals(k_old+1,j)
    1062              : 
    1063        31455 :          gnew = gvals(k_old+1,j) + dval*(xq_old(k_old+1) - xq_new(k_new))/dq_old(k_old)
    1064        31455 :          if (dbg1) write(*,*) trim(gval_names(j))
    1065              : 
    1066        31455 :          dgnew = min(delta_gval_max(k_old), delta_gval_max(k_old+1))
    1067        31455 :          gmax = gnew + dgnew
    1068        31455 :          gmin = gnew - dgnew
    1069              : 
    1070        31455 :          dq_sum = 0
    1071        91915 :          do k=k_old+1, nz_old
    1072              : 
    1073        91915 :             if (dbg1) write(*,2) 'gvals(k,j)', k, gvals(k,j), dq_sum, dq_old(k-1)
    1074              : 
    1075        91915 :             if (gvals(k,j) <= gmax .and. gvals(k,j) >= gmin) then
    1076        75436 :                if (xq_old(k-1) >= xq_new(k_new)) then
    1077        75436 :                   dq_sum = dq_sum + dq_old(k-1)
    1078              :                else
    1079            0 :                   if (dq_sum /= 0) then
    1080            0 :                      write(*,*) '(dq_sum /= 0)'
    1081            0 :                      write(*,*) 'pick1_dq'
    1082            0 :                      ierr = -1
    1083            0 :                      return
    1084              :                   end if
    1085            0 :                   dq_sum = xq_old(k) - xq_new(k_new)
    1086              :                end if
    1087        75436 :                if (is_bad(dq_sum)) then
    1088            0 :                   write(*,2) 'dq_sum', k, dq_sum
    1089            0 :                   write(*,*) 'pick1_dq'
    1090            0 :                   ierr = -1
    1091            0 :                   if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'mesh plan')
    1092            0 :                   return
    1093              :                end if
    1094        75436 :                if (dq_sum >= next_dq_max) exit
    1095        60690 :                if (dq_sum >= default) then
    1096            0 :                   dq_sum = default; exit
    1097              :                end if
    1098        60690 :                if (k < nz_old) cycle
    1099              :                ! pick location inside center zone
    1100          230 :                if (dbg1) write(*,*) 'pick location inside center zone'
    1101          230 :                if (gvals(k-1,j) < gvals(k,j)) then  ! see where reach gmax in center cell
    1102          230 :                   dq_next = find0(0d0, gvals(k-1,j)-gmax, dq_old(k-1), gvals(k,j)-gmax)
    1103          230 :                   if (dbg1) write(*,1) 'gvals(k-1,j) < gvals(k,j)', dq_next
    1104            0 :                else if (gvals(k-1,j) > gvals(k,j)) then  ! see where reach gmin
    1105            0 :                   dq_next = find0(0d0, gvals(k-1,j)-gmin, dq_old(k-1), gvals(k,j)-gmin)
    1106            0 :                   if (dbg1) then
    1107            0 :                      write(*,1) 'gvals(k-1,j)-gmin', gvals(k-1,j)-gmin
    1108            0 :                      write(*,1) 'gvals(k,j)-gmin', gvals(k,j)-gmin
    1109            0 :                      write(*,1) 'dq_old(k-1)', dq_old(k-1)
    1110            0 :                      write(*,1) 'gvals(k-1,j) > gvals(k,j)', dq_next
    1111            0 :                      call mesa_error(__FILE__,__LINE__,'debug pick1_dq')
    1112              :                   end if
    1113              :                else  ! we're done -- don't need another point for this gval
    1114            0 :                   dq_sum = default; exit  ! just return the default
    1115              :                end if
    1116          230 :                if (dq_next > 1 - (xq_new(k_new) + min_dq)) then
    1117          190 :                   dq_sum = default
    1118              :                else
    1119           40 :                   dq_sum = dq_sum + dq_next
    1120              :                end if
    1121              :                exit
    1122              :             end if
    1123              : 
    1124        16479 :             if (gvals(k,j) > gmax) then  ! estimate where = gmax
    1125        16479 :                dq_next = find0(0d0, gvals(k-1,j)-gmax, dq_old(k-1), gvals(k,j)-gmax)
    1126            0 :             else if (gvals(k,j) < gmin) then  ! estimate where = gmin
    1127            0 :                dq_next = find0(0d0, gvals(k-1,j)-gmin, dq_old(k-1), gvals(k,j)-gmin)
    1128              :             end if
    1129        16479 :             if (is_bad(dq_next)) then
    1130            0 :                write(*,2) 'dq_next', k, dq_next
    1131            0 :                write(*,*) 'gvals(k,j) > gmax', gvals(k,j) > gmax
    1132            0 :                write(*,*) 'gvals(k,j) < gmin', gvals(k,j) < gmin
    1133            0 :                write(*,3) 'gvals(k-1,j)', k-1, j, gvals(k-1,j)
    1134            0 :                write(*,2) 'gmax', k, gmax
    1135            0 :                write(*,3) 'gvals(k,j)', k, j, gvals(k,j)
    1136            0 :                write(*,2) 'gmin', k, gmin
    1137            0 :                write(*,2) 'dq_old(k-1)', k, dq_old(k-1)
    1138            0 :                write(*,*) 'pick1_dq'
    1139            0 :                ierr = -1
    1140            0 :                if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'mesh plan')
    1141            0 :                return
    1142              :             end if
    1143        16479 :             if (xq_old(k-1) >= xq_new(k_new)) then
    1144        16479 :                dq_sum = dq_sum + dq_next
    1145              :             else
    1146            0 :                if (dq_sum /= 0) then
    1147            0 :                   write(*,*) '(dq_sum /= 0)'
    1148            0 :                   write(*,*) 'pick1_dq'
    1149            0 :                   ierr = -1
    1150            0 :                   return
    1151              :                end if
    1152            0 :                dq_sum = dq_next - (xq_new(k_new) - xq_old(k-1))
    1153              :             end if
    1154        75206 :             exit
    1155              : 
    1156              :          end do
    1157              : 
    1158        31455 :          if (dbg1) then
    1159            0 :             write(*,1) 'after loop: dq_sum', dq_sum, min_dq, default
    1160              :          end if
    1161              : 
    1162        31455 :          dq_sum = max(min_dq, dq_sum)
    1163        31455 :          xq = xq_new(k_new) + dq_sum
    1164        31455 :          if (dbg1) write(*,1) 'before round_off_xq', xq
    1165        31455 :          xq = round_off_xq(k_old, nz_old, max_num_subcells, xq, xq_old, dq_old, sz, ierr)
    1166        31455 :          if (ierr /= 0) return
    1167        31455 :          if (dbg1) then
    1168            0 :             write(*,1) 'after round_off_xq: xq', xq
    1169            0 :             write(*,1) 'xq_new(k_new)', xq_new(k_new)
    1170            0 :             write(*,1) 'xq - xq_new(k_new)', xq - xq_new(k_new)
    1171            0 :             write(*,1) 'sz', sz
    1172            0 :             write(*,1) 'min_dq', min_dq
    1173            0 :             write(*,1) 'default', default
    1174              :          end if
    1175        31455 :          pick1_dq = max(min_dq, sz, xq - xq_new(k_new))
    1176              : 
    1177        31455 :          if (is_xa_function .and. pick1_dq < min_dq_for_xa) &
    1178          310 :             pick1_dq = min_dq_for_xa
    1179              : 
    1180        31455 :          if (is_logT_function .and. pick1_dq < min_dq_for_logT) &
    1181            0 :             pick1_dq = min_dq_for_logT
    1182              : 
    1183        31455 :          if (dbg1) then
    1184            0 :             write(*,2) 'dq_sum', k_new, dq_sum
    1185            0 :             write(*,2) 'xq', k_new, xq
    1186            0 :             write(*,2) 'pick1_dq', k_new, pick1_dq
    1187            0 :             write(*,2) 'log pick1_dq', k_new, log10(pick1_dq)
    1188              :          end if
    1189              : 
    1190        31455 :       end function pick1_dq
    1191              : 
    1192              : 
    1193        31455 :       real(dp) function round_off_xq(k_old, nz_old, n, xq, xq_old, dq_old, sz, ierr)
    1194              :          ! adjust to match one of the candidate subcell locations
    1195              :          ! this prevents generating too many candidate new points
    1196              :          integer, intent(in) :: k_old, nz_old, n  ! n is number of subcells
    1197              :          real(dp), intent(in) :: xq, xq_old(:), dq_old(:)
    1198              :          real(dp), intent(out) :: sz  ! subcell size at new location
    1199              :          integer, intent(out) :: ierr
    1200              : 
    1201        31455 :          real(dp) :: dq, tmp
    1202              :          integer :: i, k, j, knxt
    1203              :          include 'formats'
    1204        31455 :          ierr = 0
    1205        31455 :          knxt = 0
    1206        31455 :          round_off_xq = -1
    1207        31455 :          if (xq >= xq_old(nz_old)) then
    1208          230 :             knxt = nz_old+1
    1209              :          else
    1210        31225 :             j = -1
    1211        31225 :             do k=k_old,1,-1
    1212        31225 :                if (xq_old(k) <= xq) then
    1213        31225 :                   j = k+1; exit
    1214              :                end if
    1215              :             end do
    1216        31225 :             if (j <= 1) then
    1217            0 :                write(*,*) 'logic error in mesh plan: round_off_xq'
    1218            0 :                ierr = -1
    1219            0 :                return
    1220              :             end if
    1221       104641 :             do k=j,nz_old
    1222       104641 :                if (xq_old(k) > xq) then
    1223              :                   knxt = k; exit
    1224              :                end if
    1225              :             end do
    1226              :          end if
    1227              :          ! xq is in old cell knxt-1
    1228              :          ! move location to next subcell boundary
    1229        31455 :          dq = xq - xq_old(knxt-1)
    1230        31455 :          sz = dq_old(knxt-1)/dble(n)  ! size of subcells
    1231        31455 :          tmp = dq/sz
    1232        31455 :          if(tmp>huge(n)) tmp=huge(n)
    1233        31455 :          i = max(1,floor(tmp))
    1234        31455 :          if (knxt > nz_old) i = min(i,n/2)  ! limit extrapolation into center
    1235        31455 :          dq = i*sz
    1236        31455 :          round_off_xq = xq_old(knxt-1) + dq
    1237        31455 :          if (dq <= 0) then
    1238            0 :             write(*,2) 'dq', knxt-1, dq, xq, xq_old(knxt-1), dq_old(knxt-1)
    1239            0 :             write(*,3) 'i n sz', i, n, sz
    1240            0 :             write(*,*) 'round_off_xq'
    1241            0 :             ierr = -1
    1242            0 :             return
    1243              :          end if
    1244        31455 :       end function round_off_xq
    1245              : 
    1246              :       end module mesh_plan
        

Generated by: LCOV version 2.0-1