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

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2019  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              :       module adjust_xyz
      21              : 
      22              :       use star_private_def
      23              :       use const_def, only: dp, ln10
      24              :       use chem_def
      25              :       use utils_lib
      26              : 
      27              :       implicit none
      28              : 
      29              :       private
      30              :       public :: change_net
      31              :       public :: change_small_net
      32              :       public :: get_xa_for_standard_metals
      33              :       public :: get_xa_for_accretion
      34              :       public :: set_z
      35              :       public :: set_y
      36              :       public :: set_uniform_composition
      37              :       public :: set_standard_composition
      38              :       public :: set_uniform_xa_from_file
      39              :       public :: set_composition
      40              :       public :: do_change_to_xa_for_accretion
      41              :       public :: set_abundance_ratio
      42              :       public :: do_replace
      43              :       public :: do_set_abundance
      44              :       public :: do_uniform_mix_section
      45              :       public :: do_uniform_mix_envelope_down_to_t
      46              : 
      47              :       logical, parameter :: dbg = .false.
      48              : 
      49              :       contains
      50              : 
      51            0 :       subroutine change_net( &
      52              :             id, adjust_abundances_for_new_isos, new_net_name, ierr)
      53              :          integer, intent(in) :: id
      54              :          logical, intent(in) :: adjust_abundances_for_new_isos
      55              :          character (len=*), intent(in) :: new_net_name
      56              :          integer, intent(out) :: ierr
      57              :          call do_composition_fixup( &
      58            0 :             id, adjust_abundances_for_new_isos, new_net_name, ierr)
      59            0 :       end subroutine change_net
      60              : 
      61              : 
      62            0 :       subroutine change_small_net( &
      63              :             id, adjust_abundances_for_new_isos, new_net_name, ierr)
      64              :          integer, intent(in) :: id
      65              :          logical, intent(in) :: adjust_abundances_for_new_isos
      66              :          character (len=*), intent(in) :: new_net_name
      67              :          integer, intent(out) :: ierr
      68              :          call do_composition_fixup( &
      69            0 :             id, adjust_abundances_for_new_isos, new_net_name, ierr)
      70            0 :       end subroutine change_small_net
      71              : 
      72              : 
      73            0 :       subroutine do_composition_fixup( &
      74              :             id, adjust_abundances_for_new_isos, new_net_name, ierr)
      75              :          use net, only: do_micro_change_net
      76              :          use eos_def, only: num_eos_basic_results, num_eos_d_dxa_results
      77              :          integer, intent(in) :: id
      78              :          logical, intent(in) :: adjust_abundances_for_new_isos
      79              :          character (len=*), intent(in) :: new_net_name
      80              :          integer, intent(out) :: ierr
      81              : 
      82              :          type (star_info), pointer :: s
      83              :          integer :: old_num_isos, old_num_reactions
      84            0 :          integer :: old_net_iso(num_chem_isos)
      85            0 :          integer :: old_chem_id(num_chem_isos)
      86              :          integer :: species, nz, num_reactions
      87            0 :          integer, pointer :: chem_id(:)
      88              :          character (len=net_name_len) :: old_net_name
      89              : 
      90            0 :          call get_star_ptr(id, s, ierr)
      91            0 :          if (ierr /= 0) return
      92              : 
      93            0 :          if (new_net_name == s% net_name) return
      94              : 
      95              :          old_net_name = s% net_name
      96            0 :          old_num_isos = s% species
      97            0 :          old_num_reactions = s% num_reactions
      98            0 :          old_net_iso = s% net_iso
      99            0 :          old_chem_id(1:old_num_isos) = s% chem_id(1:old_num_isos)
     100              : 
     101            0 :          call do_micro_change_net(s, new_net_name, ierr)
     102            0 :          if (ierr /= 0) then
     103            0 :             s% retry_message = 'micro_change_net failed'
     104            0 :             if (s% report_ierr) write(*,*) s% retry_message
     105            0 :             return
     106              :          end if
     107              : 
     108            0 :          species = s% species
     109            0 :          nz = max(s% nz, s% prev_mesh_nz)
     110            0 :          chem_id => s% chem_id
     111            0 :          num_reactions = s% num_reactions
     112              : 
     113            0 :          write(*,*) 'change to "' // trim(new_net_name)//'"'
     114            0 :          write(*,*) 'number of species', s% species
     115              : 
     116            0 :          call realloc(s% dxdt_nuc); if (ierr /= 0) return
     117            0 :          call realloc(s% dxdt_nuc_start); if (ierr /= 0) return
     118            0 :          call realloc(s% d_epsnuc_dX); if (ierr /= 0) return
     119            0 :          call realloc(s% d_dxdt_nuc_dRho); if (ierr /= 0) return
     120            0 :          call realloc(s% d_dxdt_nuc_dT); if (ierr /= 0) return
     121              : 
     122            0 :          call realloc(s% dxdt_mix); if (ierr /= 0) return
     123              : 
     124            0 :          call realloc(s% d_eps_grav_dX); if (ierr /= 0) return
     125            0 :          call realloc(s% dlnE_dxa_for_partials); if (ierr /= 0) return
     126            0 :          call realloc(s% dlnPeos_dxa_for_partials); if (ierr /= 0) return
     127              : 
     128            0 :          call realloc(s% extra_diffusion_factor); if (ierr /= 0) return
     129            0 :          call realloc(s% edv); if (ierr /= 0) return
     130            0 :          call realloc(s% v_rad); if (ierr /= 0) return
     131            0 :          call realloc(s% g_rad); if (ierr /= 0) return
     132            0 :          call realloc(s% typical_charge); if (ierr /= 0) return
     133            0 :          call realloc(s% diffusion_dX); if (ierr /= 0) return
     134            0 :          call realloc(s% diffusion_D_self); if (ierr /= 0) return
     135              : 
     136            0 :          if (associated(s% d_dXdt_nuc_dX)) deallocate(s% d_dXdt_nuc_dX)
     137            0 :          allocate(s% d_dXdt_nuc_dX(species, species, nz + nz_alloc_extra), stat=ierr)
     138            0 :          if (ierr /= 0) return
     139              : 
     140            0 :          if (associated(s% d_eos_dxa)) deallocate(s% d_eos_dxa)
     141            0 :          allocate(s% d_eos_dxa(num_eos_d_dxa_results, species, nz + nz_alloc_extra), stat=ierr)
     142            0 :          if (ierr /= 0) return
     143              : 
     144            0 :          call realloc(s% xa_sub_xa_start); if (ierr /= 0) return
     145            0 :          call realloc(s% xa_start); if (ierr /= 0) return
     146            0 :          call realloc(s% prev_mesh_xa); if (ierr /= 0) return
     147            0 :          call do_xa(s% nz, s% xh, s% xa)
     148            0 :          if (s% generations > 1) call do_xa(s% nz_old, s% xh_old, s% xa_old)
     149              : 
     150            0 :          call realloc_reactions(s% raw_rate)
     151            0 :          if(ierr/=0) return
     152            0 :          call realloc_reactions(s% screened_rate)
     153            0 :          if(ierr/=0) return
     154            0 :          call realloc_reactions(s% eps_nuc_rate)
     155            0 :          if(ierr/=0) return
     156            0 :          call realloc_reactions(s% eps_neu_rate)
     157            0 :          if(ierr/=0) return
     158              : 
     159            0 :          s% need_to_setvars = .true.
     160            0 :          s% prev_mesh_species_or_nvar_hydro_changed = .true.
     161              : 
     162              :          contains
     163              : 
     164            0 :          subroutine do_xa(nz, xh, xa_startv)
     165            0 :             use net_lib, only: clean_up_fractions
     166              :             integer, intent(in) :: nz
     167              :             real(dp), pointer :: xh(:,:)
     168              :             real(dp), pointer :: xa_startv(:,:)
     169              :             real(dp), pointer :: xa_new(:,:)
     170              :             real(dp), parameter :: max_sum_abs = 10d0
     171              :             real(dp), parameter :: xsum_tol = 1d-2
     172            0 :             allocate(xa_new(species, nz + nz_alloc_extra), stat=ierr)
     173            0 :             if (ierr /= 0) return
     174              :             call set_x_new( &
     175              :                s, adjust_abundances_for_new_isos, &
     176              :                nz, old_num_isos, species, xh, xa_startv, xa_new, &
     177            0 :                old_chem_id, old_net_iso, chem_id, ierr)
     178            0 :             if (associated(xa_startv)) deallocate(xa_startv)
     179            0 :             xa_startv => xa_new
     180            0 :          end subroutine do_xa
     181              : 
     182            0 :          subroutine realloc(ptr)
     183              :             real(dp), pointer :: ptr(:, :)
     184            0 :             if (associated(ptr)) deallocate(ptr)
     185            0 :             allocate(ptr(species, nz + nz_alloc_extra), stat=ierr)
     186            0 :          end subroutine realloc
     187              : 
     188            0 :          subroutine realloc_reactions(ptr)
     189              :             real(dp), pointer :: ptr(:, :)
     190            0 :             if (associated(ptr)) deallocate(ptr)
     191            0 :             allocate(ptr(num_reactions, nz + nz_alloc_extra), stat=ierr)
     192            0 :          end subroutine realloc_reactions
     193              : 
     194              :          subroutine realloc_integer(ptr)
     195              :             integer, pointer :: ptr(:, :)
     196              :             if (associated(ptr)) deallocate(ptr)
     197              :             allocate(ptr(species, nz + nz_alloc_extra), stat=ierr)
     198              :          end subroutine realloc_integer
     199              : 
     200              :       end subroutine do_composition_fixup
     201              : 
     202              : 
     203            0 :       subroutine set_x_new( &
     204              :             s, adjust_abundances_for_new_isos, &
     205              :             nz, old_num_isos, species, xh, xa_startv, xa_new, &
     206            0 :             old_chem_id, old_net_iso, chem_id, ierr)
     207              :          use net_lib, only: clean1
     208              :          type (star_info), pointer :: s
     209              :          logical, intent(in) :: adjust_abundances_for_new_isos
     210              :          integer, intent(in) :: nz, old_num_isos, species
     211              :          real(dp), pointer :: xh(:,:)
     212              :          real(dp), pointer :: xa_startv(:,:)
     213              :          real(dp), pointer :: xa_new(:,:)
     214              :          integer, pointer :: chem_id(:)
     215              :          integer, intent(in) :: old_chem_id(old_num_isos), old_net_iso(num_chem_isos)
     216              :          integer, intent(out) :: ierr
     217              : 
     218              :          integer :: k, op_err
     219              :          real(dp), parameter :: max_sum_abs = 10
     220              :          real(dp), parameter :: xsum_tol = 1d-2
     221              :          include 'formats'
     222              : 
     223            0 :          ierr = 0
     224            0 : !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
     225              :          do k=1, nz
     226              :             call set_new_abundances( &
     227              :                s, adjust_abundances_for_new_isos, &
     228              :                nz, old_num_isos, species, xh, xa_startv, xa_new, k, &
     229              :                old_chem_id, old_net_iso, chem_id, op_err)
     230              :             if (op_err /= 0) ierr = op_err
     231              :             call clean1(species, xa_new(1:species,k), max_sum_abs, xsum_tol, op_err)
     232              :             if (op_err /= 0) ierr = op_err
     233              :          end do
     234              : !$OMP END PARALLEL DO
     235            0 :          if (ierr /= 0) then
     236            0 :             s% retry_message = 'set_new_abundances failed in set_x_new'
     237            0 :             if (s% report_ierr) write(*, *) s% retry_message
     238              :             return
     239              :          end if
     240              : 
     241            0 :          s% need_to_setvars = .true.
     242              : 
     243            0 :       end subroutine set_x_new
     244              : 
     245              : 
     246            0 :       subroutine set_new_abundances( &
     247              :             s, adjust_abundances_for_new_isos, nz, &
     248              :             old_num_isos, species, xh, xa_startv, xa_new, &
     249            0 :             k, old_chem_id, old_net_iso, chem_id, ierr)
     250            0 :          use chem_lib, only: chem_Xsol
     251              :          type (star_info), pointer :: s
     252              :          logical, intent(in) :: adjust_abundances_for_new_isos
     253              :          integer, intent(in) :: nz, old_num_isos, species, k
     254              :          real(dp), pointer :: xh(:,:)
     255              :          real(dp), pointer :: xa_startv(:,:)
     256              :          real(dp), pointer :: xa_new(:,:)
     257              :          integer, pointer :: chem_id(:)
     258              :          integer, intent(in) :: &
     259              :             old_chem_id(old_num_isos), old_net_iso(num_chem_isos)
     260              :          integer, intent(out) :: ierr
     261              : 
     262              :          real(dp) :: &
     263            0 :             total_neut, total_h, total_he, total_c, total_n, total_o, &
     264            0 :             total_ne, total_mg, total_si, total_s, total_ar, total_ca, &
     265            0 :             total_fe, total_co, other, &
     266              :             old_total_neut, old_total_h, old_total_he, old_total_c, old_total_n, old_total_o, &
     267            0 :             old_total_ne, old_total_mg, old_total_si, old_total_s, old_total_ar, old_total_ca, &
     268            0 :             old_total_fe, old_total_co, old_total_ni, old_other, &
     269            0 :             lgT, zfrac, xsol, lgT_lo, lgT_hi
     270              :          integer :: i, j, cid, Z
     271              :          character(len=solnamelen) :: sol_name
     272              :          logical :: dbg, did_total_neut, did_total_h, did_total_he, &
     273              :             did_total_c, did_total_n, did_total_o, did_total_ne, &
     274              :             did_total_mg, did_total_si, did_total_s, did_total_ar, did_total_ca, &
     275              :             did_total_fe, did_total_co, did_total_ni, did_total_other
     276              : 
     277              :          include 'formats'
     278              : 
     279            0 :          dbg = .false.  !(k == nz) .or. (k == nz-1)
     280              : 
     281            0 :          ierr = 0
     282            0 :          zfrac = s% initial_z / zsol
     283            0 :          lgT_lo = s% lgT_lo_for_set_new_abundances
     284            0 :          lgT_hi = s% lgT_hi_for_set_new_abundances
     285              : 
     286              :          if (dbg) then
     287              :             write(*,'(A)')
     288              :             write(*,2) 'set_new_abundances', k
     289              :             write(*,2) 'old_num_isos', old_num_isos
     290              :             do j=1,old_num_isos
     291              :                write(*,2) 'old ' // chem_isos% name(old_chem_id(j)), k, xa_startv(j,k)
     292              :             end do
     293              :             write(*,'(A)')
     294              :          end if
     295              : 
     296            0 :          old_total_neut = 0
     297            0 :          old_total_h = 0
     298            0 :          old_total_he = 0
     299            0 :          old_total_c = 0
     300            0 :          old_total_n = 0
     301            0 :          old_total_o = 0
     302            0 :          old_total_ne = 0
     303            0 :          old_total_mg = 0
     304            0 :          old_total_si = 0
     305            0 :          old_total_s = 0
     306            0 :          old_total_ar = 0
     307            0 :          old_total_ca = 0
     308            0 :          old_total_fe = 0
     309            0 :          old_total_co = 0
     310            0 :          old_total_ni = 0
     311            0 :          old_other = 0
     312            0 :          do j=1, old_num_isos
     313            0 :             Z = chem_isos% Z(old_chem_id(j))
     314            0 :             if (Z == 0) then
     315            0 :                old_total_neut = old_total_neut + xa_startv(j,k)
     316              :             else if (Z == 1) then
     317            0 :                old_total_h = old_total_h + xa_startv(j,k)
     318              :             else if (Z == 2) then
     319            0 :                old_total_he = old_total_he + xa_startv(j,k)
     320              :             else if (Z == 6) then
     321            0 :                old_total_c = old_total_c + xa_startv(j,k)
     322              :             else if (Z == 7) then
     323            0 :                old_total_n = old_total_n + xa_startv(j,k)
     324              :             else if (Z == 8) then
     325            0 :                old_total_o = old_total_o + xa_startv(j,k)
     326              :             else if (Z == 10) then
     327            0 :                old_total_ne = old_total_ne + xa_startv(j,k)
     328              :             else if (Z == 12) then
     329            0 :                old_total_mg = old_total_mg + xa_startv(j,k)
     330              :             else if (Z == 14) then
     331            0 :                old_total_si = old_total_si + xa_startv(j,k)
     332              :             else if (Z == 16) then
     333            0 :                old_total_s = old_total_s + xa_startv(j,k)
     334              :             else if (Z == 18) then
     335            0 :                old_total_ar = old_total_ar + xa_startv(j,k)
     336              :             else if (Z == 20) then
     337            0 :                old_total_ca = old_total_ca + xa_startv(j,k)
     338              :             else if (Z == 26) then
     339            0 :                old_total_fe = old_total_fe + xa_startv(j,k)
     340              :             else if (Z == 27) then
     341            0 :                old_total_co = old_total_co + xa_startv(j,k)
     342              :             else if (Z == 28) then
     343            0 :                old_total_fe = old_total_fe + xa_startv(j,k)
     344              :             else
     345            0 :                old_other = old_other + xa_startv(j,k)
     346              :             end if
     347              :          end do
     348              : 
     349            0 :          lgT = get_test_lgT(k)
     350              :          ! copy old isos and set abundances for new ones
     351            0 :          do j=1, species
     352            0 :             cid = chem_id(j)
     353            0 :             i = old_net_iso(cid)  ! old index number for this species
     354            0 :             if (i /= 0) then
     355            0 :                xa_new(j,k) = xa_startv(i,k)
     356            0 :             else if (.not. adjust_abundances_for_new_isos) then
     357            0 :                xa_new(j,k) = 0d0
     358              :             else
     359            0 :                if (chem_isos% Z(cid) > 5) then
     360            0 :                   sol_name = chem_isos% name(cid)
     361            0 :                   xsol = chem_Xsol(sol_name)
     362            0 :                   xa_new(j,k) = zfrac*xsol
     363              :                   if (dbg) then
     364              :                      write(*,2) 'xa new ' // trim(sol_name), j, xa_new(j,k), xsol, zfrac
     365              :                   end if
     366              :                else
     367              :                   ! cannot simply add light elements to high temperature region
     368              :                   ! or will create an explosive situation that won't converge
     369            0 :                   if (lgT >= lgT_hi) then  ! don't add any
     370            0 :                      xa_new(j,k) = 0
     371              :                   else
     372            0 :                      sol_name = chem_isos% name(cid)
     373            0 :                      xsol = chem_Xsol(sol_name)
     374            0 :                      if (lgT > lgT_lo) then  ! interpolate
     375              :                         xa_new(j, k) = &
     376            0 :                            xsol*0.5d0*(1+cospi((lgT-lgT_lo)/(lgT_hi-lgT_lo)))
     377              :                      else  ! add solar
     378            0 :                         xa_new(j,k) = xsol
     379              :                      end if
     380              :                   end if
     381              :                end if
     382              :             end if
     383              :          end do
     384              : 
     385              :          total_neut = 0
     386              :          total_h = 0
     387              :          total_he = 0
     388              :          total_c = 0
     389              :          total_n = 0
     390              :          total_o = 0
     391              :          total_ne = 0
     392              :          total_mg = 0
     393              :          total_si = 0
     394              :          total_s = 0
     395              :          total_ar = 0
     396              :          total_ca = 0
     397              :          total_fe = 0
     398              :          total_co = 0
     399              :          total_fe = 0
     400              :          other = 0
     401            0 :          do j=1, species
     402            0 :             select case(int(chem_isos% Z(chem_id(j))))
     403              :                case (0)
     404            0 :                   total_neut = total_neut + xa_new(j,k)
     405              :                case (1)
     406            0 :                   total_h = total_h + xa_new(j,k)
     407              :                case (2)
     408            0 :                   total_he = total_he + xa_new(j,k)
     409              :                case (6)
     410            0 :                   total_c = total_c + xa_new(j,k)
     411              :                case (7)
     412            0 :                   total_n = total_n + xa_new(j,k)
     413              :                case (8)
     414            0 :                   total_o = total_o + xa_new(j,k)
     415              :                case (10)
     416            0 :                   total_ne = total_ne + xa_new(j,k)
     417              :                case (12)
     418            0 :                   total_mg = total_mg + xa_new(j,k)
     419              :                case (14)
     420            0 :                   total_si = total_si + xa_new(j,k)
     421              :                case (16)
     422            0 :                   total_s = total_s + xa_new(j,k)
     423              :                case (18)
     424            0 :                   total_ar = total_ar + xa_new(j,k)
     425              :                case (20)
     426            0 :                   total_ca = total_ca + xa_new(j,k)
     427              :                case (26)
     428            0 :                   total_fe = total_fe + xa_new(j,k)
     429              :                case (27)
     430            0 :                   total_co = total_co + xa_new(j,k)
     431              :                case (28)
     432            0 :                   total_fe = total_fe + xa_new(j,k)
     433              :                case default
     434            0 :                   other = other + xa_new(j,k)
     435              :             end select
     436              :          end do
     437              : 
     438              :          if (dbg) then
     439              :             write(*,1) 'old_total_n', old_total_n
     440              :             write(*,1) 'total_n', total_n
     441              :             write(*,1) 'old_total_n/total_n', old_total_n/total_n
     442              :          end if
     443              : 
     444            0 :          did_total_neut = .false.
     445            0 :          did_total_h = .false.
     446            0 :          did_total_he = .false.
     447            0 :          did_total_c = .false.
     448            0 :          did_total_n = .false.
     449            0 :          did_total_o = .false.
     450            0 :          did_total_ne = .false.
     451            0 :          did_total_mg = .false.
     452            0 :          did_total_si = .false.
     453            0 :          did_total_s = .false.
     454            0 :          did_total_ar = .false.
     455            0 :          did_total_ca = .false.
     456              :          did_total_fe = .false.
     457            0 :          did_total_co = .false.
     458            0 :          did_total_fe = .false.
     459            0 :          did_total_ni = .false.
     460            0 :          did_total_other = .false.
     461            0 :          do j=1, species
     462            0 :             select case(int(chem_isos% Z(chem_id(j))))
     463              :                case (0)
     464            0 :                   if (total_neut > 0) then
     465            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_neut/total_neut
     466            0 :                      did_total_neut = .true.
     467              :                   end if
     468              :                case (1)
     469            0 :                   if (total_h > 0) then
     470            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_h/total_h
     471            0 :                      did_total_h = .true.
     472              :                   end if
     473              :                case (2)
     474            0 :                   if (total_he > 0) then
     475            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_he/total_he
     476            0 :                      did_total_he = .true.
     477              :                   end if
     478              :                case (6)
     479            0 :                   if (total_c > 0) then
     480            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_c/total_c
     481            0 :                      did_total_c = .true.
     482              :                   end if
     483              :                case (7)
     484            0 :                   if (total_n > 0) then
     485            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_n/total_n
     486            0 :                      did_total_n = .true.
     487              :                   end if
     488              :                case (8)
     489            0 :                   if (total_o > 0) then
     490            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_o/total_o
     491            0 :                      did_total_o = .true.
     492              :                   end if
     493              :                case (10)
     494            0 :                   if (total_ne > 0) then
     495            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_ne/total_ne
     496            0 :                      did_total_ne = .true.
     497              :                   end if
     498              :                case (12)
     499            0 :                   if (total_mg > 0) then
     500            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_mg/total_mg
     501            0 :                      did_total_mg = .true.
     502              :                   end if
     503              :                case (14)
     504            0 :                   if (total_si > 0) then
     505            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_si/total_si
     506            0 :                      did_total_si = .true.
     507              :                   end if
     508              :                case (16)
     509            0 :                   if (total_s > 0) then
     510            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_s/total_s
     511            0 :                      did_total_s = .true.
     512              :                   end if
     513              :                case (18)
     514            0 :                   if (total_ar > 0) then
     515            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_ar/total_ar
     516            0 :                      did_total_ar = .true.
     517              :                   end if
     518              :                case (20)
     519            0 :                   if (total_ca > 0) then
     520            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_ca/total_ca
     521            0 :                      did_total_ca = .true.
     522              :                   end if
     523              :                case (26)
     524            0 :                   if (total_fe > 0) then
     525            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_fe/total_fe
     526            0 :                      did_total_fe = .true.
     527              :                   end if
     528              :                case (27)
     529            0 :                   if (total_co > 0) then
     530            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_co/total_co
     531            0 :                      did_total_co = .true.
     532              :                   end if
     533              :                case (28)
     534            0 :                   if (total_fe > 0) then
     535            0 :                      xa_new(j,k) = xa_new(j,k)*old_total_fe/total_fe
     536            0 :                      did_total_fe = .true.
     537              :                   end if
     538              :                case default
     539            0 :                   if (other > 0) then
     540            0 :                      xa_new(j,k) = xa_new(j,k)*old_other/other
     541            0 :                      did_total_other = .true.
     542              :                   end if
     543              :             end select
     544              :          end do
     545              : 
     546              :          ! check for leftovers and dump them into the last iso
     547            0 :          j = species
     548            0 :          if (old_total_neut > 0 .and. .not. did_total_neut) &
     549            0 :             xa_new(j,k) = xa_new(j,k) + old_total_neut
     550            0 :          if (old_total_h > 0 .and. .not. did_total_h) &
     551            0 :             xa_new(j,k) = xa_new(j,k) + old_total_h
     552            0 :          if (old_total_he > 0 .and. .not. did_total_he) &
     553            0 :             xa_new(j,k) = xa_new(j,k) + old_total_he
     554            0 :          if (old_total_c > 0 .and. .not. did_total_c) &
     555            0 :             xa_new(j,k) = xa_new(j,k) + old_total_c
     556            0 :          if (old_total_n > 0 .and. .not. did_total_n) &
     557            0 :             xa_new(j,k) = xa_new(j,k) + old_total_n
     558            0 :          if (old_total_o > 0 .and. .not. did_total_o) &
     559            0 :             xa_new(j,k) = xa_new(j,k) + old_total_o
     560            0 :          if (old_total_ne > 0 .and. .not. did_total_ne) &
     561            0 :             xa_new(j,k) = xa_new(j,k) + old_total_ne
     562            0 :          if (old_total_mg > 0 .and. .not. did_total_mg) &
     563            0 :             xa_new(j,k) = xa_new(j,k) + old_total_mg
     564            0 :          if (old_total_si > 0 .and. .not. did_total_si) &
     565            0 :             xa_new(j,k) = xa_new(j,k) + old_total_si
     566              : 
     567            0 :          if (old_total_s > 0 .and. .not. did_total_s) &
     568            0 :             xa_new(j,k) = xa_new(j,k) + old_total_s
     569            0 :          if (old_total_ar > 0 .and. .not. did_total_ar) &
     570            0 :             xa_new(j,k) = xa_new(j,k) + old_total_ar
     571            0 :          if (old_total_ca > 0 .and. .not. did_total_ca) &
     572            0 :             xa_new(j,k) = xa_new(j,k) + old_total_ca
     573            0 :          if (old_total_fe > 0 .and. .not. did_total_fe) &
     574            0 :             xa_new(j,k) = xa_new(j,k) + old_total_fe
     575            0 :          if (old_total_co > 0 .and. .not. did_total_co) &
     576            0 :             xa_new(j,k) = xa_new(j,k) + old_total_co
     577              :          if (old_total_ni > 0 .and. .not. did_total_ni) &
     578              :             xa_new(j,k) = xa_new(j,k) + old_total_ni
     579            0 :          if (old_other > 0 .and. .not. did_total_other) &
     580            0 :             xa_new(j,k) = xa_new(j,k) + old_other
     581              : 
     582            0 :          if (abs(sum(xa_new(:,k)) - 1d0) > 0.1d0) then
     583            0 : !$omp critical (new_abund)
     584            0 :             write(*,'(A)')
     585            0 :             write(*,2) 'bad sum: set_new_abundances', k, sum(xa_new(:,k))
     586            0 :             write(*,2) 'species', species
     587            0 :             do j=1,species
     588            0 :                write(*,2) trim(chem_isos% name(chem_id(j))), k, xa_new(j,k)
     589              :             end do
     590            0 :             write(*,'(A)')
     591            0 :             write(*,2) 'old_total_neut', k, old_total_neut
     592            0 :             write(*,2) 'old_total_h', k, old_total_h
     593            0 :             write(*,2) 'old_total_he', k, old_total_he
     594            0 :             write(*,2) 'old_total_c', k, old_total_c
     595            0 :             write(*,2) 'old_total_n', k, old_total_n
     596            0 :             write(*,2) 'old_total_o', k, old_total_o
     597            0 :             write(*,2) 'old_other', k, old_other
     598            0 :             write(*,'(A)')
     599            0 :             call mesa_error(__FILE__,__LINE__,'debug: set_new_abundances')
     600              : !$omp end critical (new_abund)
     601              : 
     602              :             return
     603              :          end if
     604              : 
     605            0 :          if (dbg) then
     606              :             write(*,'(A)')
     607              :             write(*,2) 'new num species', species
     608              :             do j=1,species
     609              :                write(*,2) trim(chem_isos% name(chem_id(j))), j, xa_new(j,k)
     610              :             end do
     611              :             write(*,'(A)')
     612              :             call mesa_error(__FILE__,__LINE__,'debug: set_new_abundances')
     613              :          end if
     614              : 
     615              :          contains
     616              : 
     617            0 :          real(dp) function get_test_lgT(loc)
     618            0 :             use star_utils, only: get_lnT_from_xh
     619              :             integer, intent(in) :: loc
     620              :             integer :: k, kmax
     621            0 :             get_test_lgT = get_lnT_from_xh(s,loc)/ln10
     622            0 :             kmax = min(min(s%nz,nz),size(s% mlt_D,dim=1))
     623            0 :             do k=loc+1, kmax
     624            0 :                if (s% mlt_D(k) < 1d2) return
     625            0 :                get_test_lgT = get_lnT_from_xh(s,k)/ln10
     626              :             end do
     627            0 :          end function get_test_lgT
     628              : 
     629              :       end subroutine set_new_abundances
     630              : 
     631              :       subroutine get_ag89_composition(s, species, xa, ierr)
     632              :          use chem_lib, only: chem_Xsol
     633              :          type (star_info), pointer :: s
     634              :          integer, intent(in) :: species
     635              :          real(dp) :: xa(species)
     636              :          integer, intent(out) :: ierr
     637              :          integer :: i, mg24
     638              :          ierr = 0
     639              :          do i=1, species
     640              :             xa(i) = chem_Xsol(chem_isos% name(s% chem_id(i)))
     641              :          end do
     642              :          mg24 = s% net_iso(img24)
     643              :          xa(mg24) = xa(mg24) + (1 - sum(xa(1:species)))
     644              :       end subroutine get_ag89_composition
     645              : 
     646              : 
     647            0 :       subroutine set_y(s, y, nzlo, nzhi, ierr)
     648              :          use star_utils, only: eval_current_abundance
     649              :          type (star_info), pointer :: s
     650              :          integer, intent(in) :: nzlo, nzhi
     651              :          real(dp), intent(in) :: y
     652              :          integer, intent(out) :: ierr
     653              : 
     654            0 :          real(dp) :: xh1, xhe3, xhe4, z, ratio, desired_xh1, desired_xhe4
     655              :          include 'formats'
     656              : 
     657              :          ierr = 0
     658              : 
     659            0 :          if (y == 0) then  ! convert all he4 to h1
     660            0 :             call set_abundance_ratio(s% id, ihe4, ih1, 0d0, nzlo, nzhi, ierr)
     661              :          end if
     662              : 
     663            0 :          xh1 = eval_current_abundance(s, s% net_iso(ih1), nzlo, nzhi, ierr)
     664            0 :          xhe3 = eval_current_abundance(s, s% net_iso(ihe3), nzlo, nzhi, ierr)
     665            0 :          xhe4 = eval_current_abundance(s, s% net_iso(ihe4), nzlo, nzhi, ierr)
     666            0 :          z = 1d0 - (xh1 + xhe3 + xhe4)
     667              :          ! keep xhe3 and z constant; change ratio of xh1 and xhe4
     668            0 :          desired_xhe4 = y - xhe3
     669            0 :          desired_xh1 = 1d0 - z - y
     670              : 
     671            0 :          if (desired_xh1 <= 0d0) then  ! convert all h1 to he4
     672            0 :             ratio = 0d0
     673            0 :          else if (desired_xhe4 <= 0d0) then  ! convert all he4 to h1
     674            0 :             ratio = 1d0
     675              :          else
     676            0 :             ratio = desired_xh1/desired_xhe4
     677              :          end if
     678              : 
     679            0 :          call set_abundance_ratio(s% id, ih1, ihe4, ratio, nzlo, nzhi, ierr)
     680              : 
     681            0 :       end subroutine set_y
     682              : 
     683              : 
     684            0 :       subroutine set_abundance_ratio(id, i1, i2, ratio, nzlo, nzhi, ierr)
     685              :          integer, intent(in) :: id, i1, i2, nzlo, nzhi
     686              :          real(dp), intent(in) :: ratio  ! new x(i1)/x(i2)
     687              :          integer, intent(out) :: ierr
     688              : 
     689              :          type (star_info), pointer :: s
     690              :          integer :: k, j1, j2
     691            0 :          real(dp) :: xsum
     692              : 
     693              :          ierr = 0
     694              : 
     695            0 :          call get_star_ptr(id, s, ierr)
     696            0 :          if (ierr /= 0) return
     697              : 
     698            0 :          j1 = s% net_iso(i1)
     699            0 :          j2 = s% net_iso(i2)
     700            0 :          if (j1 == 0 .or. j2 == 0) then
     701            0 :             ierr = -1
     702            0 :             return
     703              :          end if
     704              : 
     705            0 :          do k=nzlo, nzhi
     706            0 :             xsum = s% xa(j1, k) + s% xa(j2, k)
     707            0 :             s% xa(j2, k) = xsum/(1+ratio)
     708            0 :             s% xa(j1, k) = xsum - s% xa(j2, k)
     709              :          end do
     710              : 
     711            0 :          s% need_to_setvars = .true.
     712              : 
     713            0 :       end subroutine set_abundance_ratio
     714              : 
     715              : 
     716            0 :       subroutine read_xa(s, species, xa, filename, ierr)
     717              :          use chem_def
     718              :          use chem_lib
     719              :          use utils_def
     720              :          use utils_lib
     721              :          type (star_info), pointer :: s
     722              :          integer, intent(in) :: species
     723              :          real(dp) :: xa(species)
     724              :          character (len=*), intent(in) :: filename
     725              :          integer, intent(out) :: ierr
     726              : 
     727              :          integer :: iounit, t, n, i, cid, j
     728              :          character (len=strlen) :: buffer, string
     729              :          logical, parameter :: dbg = .false.
     730              : 
     731            0 :          ierr = 0
     732              : 
     733            0 :          xa(1:species) = 0  ! default
     734              : 
     735            0 :          open(newunit=iounit, file=trim(filename), action='read', status='old', iostat=ierr)
     736            0 :          if (ierr /= 0) then
     737            0 :             write(*,*) 'failed to open abundance specification file "' // trim(filename)//'"'
     738            0 :             return
     739              :          end if
     740              : 
     741            0 :          n = 0
     742            0 :          i = 0
     743              : 
     744              :          do
     745            0 :             t = token(iounit, n, i, buffer, string)
     746            0 :             select case(t)
     747              :                case(name_token)  ! iso name
     748            0 :                   cid = chem_get_iso_id(string)
     749            0 :                   if (cid <= 0) then
     750            0 :                      write(*,*) 'reading ' // trim(filename)
     751            0 :                      write(*,*) 'unknown chem name ' // trim(string)
     752            0 :                      ierr = -1
     753            0 :                      call cleanup
     754            0 :                      return
     755              :                   end if
     756            0 :                   j = s% net_iso(cid)
     757            0 :                   if (j == 0) then
     758            0 :                      write(*,*) 'reading ' // trim(filename)
     759            0 :                      write(*,*) 'iso not in current net ' // trim(string)
     760            0 :                      ierr = -1
     761            0 :                      call cleanup
     762            0 :                      return
     763              :                   end if
     764            0 :                   t = token(iounit, n, i, buffer, string)
     765            0 :                   if (t /= name_token) then
     766            0 :                      write(*,*) 'reading ' // trim(filename)
     767              :                      write(*,*) 'failed in reading abundance value for ' // &
     768            0 :                         trim(chem_isos% name(cid))
     769            0 :                      ierr = -1
     770            0 :                      call cleanup
     771            0 :                      return
     772              :                   end if
     773              : 
     774              :                   !read(string,fmt=*,iostat=ierr) xa(j)
     775            0 :                   call str_to_double(string, xa(j), ierr)
     776            0 :                   if (ierr /= 0 .or. xa(j) > 1 .or. xa(j) < 0) then
     777            0 :                      write(*,*) 'reading ' // trim(filename)
     778              :                      write(*,*) 'invalid number given as abundance value for ' // &
     779            0 :                         trim(chem_isos% name(cid))
     780            0 :                      ierr = -1
     781            0 :                      call cleanup
     782            0 :                      return
     783              :                   end if
     784              :                case(eof_token)
     785            0 :                   exit
     786              :                case default
     787            0 :                   write(*,*) 'error in reading abundance file ' // trim(filename)
     788            0 :                   ierr = -1
     789            0 :                   call cleanup
     790            0 :                   return
     791              :             end select
     792              : 
     793              :          end do
     794              : 
     795            0 :          call cleanup
     796              : 
     797            0 :          if (abs(sum(xa(1:species)) - 1d0) > 1d-6) then
     798            0 :             write(*,*) 'reading ' // trim(filename)
     799            0 :             write(*,*) 'abundances fail to add to 1.0:  sum - 1 = ', sum(xa(:)) - 1d0
     800            0 :             ierr = -1
     801            0 :             return
     802              :          end if
     803              : 
     804            0 :          xa(1:species) = xa(1:species)/sum(xa)
     805              : 
     806              :          contains
     807              : 
     808            0 :          subroutine cleanup
     809            0 :             close(iounit)
     810            0 :          end subroutine cleanup
     811              : 
     812              :       end subroutine read_xa
     813              : 
     814              : 
     815            0 :       subroutine set_uniform_xa_from_file(id, file_for_uniform_xa, ierr)
     816              :          integer, intent(in) :: id
     817              :          character (len=*), intent(in) :: file_for_uniform_xa
     818              :          integer, intent(out) :: ierr
     819              :          type (star_info), pointer :: s
     820            0 :          call get_star_ptr(id, s, ierr)
     821            0 :          if (ierr /= 0) return
     822            0 :          call doit(s% species)
     823              : 
     824              :          contains
     825              : 
     826            0 :          subroutine doit(species)
     827              :             integer, intent(in) :: species
     828            0 :             real(dp) :: xa(species)
     829            0 :             call read_xa(s, species, xa, file_for_uniform_xa, ierr)
     830            0 :             if (ierr /= 0) return
     831            0 :             call set_uniform_composition(id, species, xa, ierr)
     832            0 :          end subroutine doit
     833              : 
     834              :       end subroutine set_uniform_xa_from_file
     835              : 
     836              : 
     837            0 :       subroutine set_uniform_composition(id, species, xa, ierr)
     838              :          integer, intent(in) :: species
     839              :          real(dp), intent(in) :: xa(species)
     840              :          integer, intent(in) :: id
     841              :          integer, intent(out) :: ierr
     842              :          type (star_info), pointer :: s
     843            0 :          call get_star_ptr(id, s, ierr)
     844            0 :          if (ierr /= 0) return
     845            0 :          call set_composition(id, 1, s% nz, species, xa, ierr)
     846              :       end subroutine set_uniform_composition
     847              : 
     848              : 
     849            0 :       subroutine set_composition(id, nzlo, nzhi, num_species, xa_new, ierr)
     850              :          integer, intent(in) :: nzlo, nzhi, num_species
     851              :          real(dp), intent(in) :: xa_new(num_species)
     852              :          integer, intent(in) :: id
     853              :          integer, intent(out) :: ierr
     854              :          integer :: j, k, nz, species
     855              :          type (star_info), pointer :: s
     856              :          include 'formats'
     857            0 :          call get_star_ptr(id, s, ierr)
     858            0 :          if (ierr /= 0) return
     859            0 :          nz = s% nz
     860            0 :          species = s% species
     861            0 :          if (num_species /= species) then
     862            0 :             ierr = -1
     863            0 :             s% retry_message = 'set_composition requires number of species to match current model'
     864            0 :             if (s% report_ierr) write(*, *) s% retry_message
     865            0 :             return
     866              :          end if
     867            0 :          if (nzlo < 1 .or. nzhi > nz) then
     868            0 :             ierr = -1
     869            0 :             s% retry_message = 'set_composition requires nzlo and nzhi to be within 1 to current num zones'
     870            0 :             if (s% report_ierr) write(*, *) s% retry_message
     871            0 :             return
     872              :          end if
     873            0 :          if (abs(1d0-sum(xa_new(1:species))) > 1d-6) then
     874            0 :             ierr = -1
     875            0 :             s% retry_message = 'set_composition requires new mass fractions to add to 1'
     876            0 :             if (s% report_ierr) write(*, *) s% retry_message
     877            0 :             return
     878              :          end if
     879            0 :          do k=nzlo,nzhi
     880            0 :             do j=1,species
     881            0 :                s% xa(j,k) = xa_new(j)
     882              :             end do
     883              :          end do
     884            0 :          ierr = 0
     885              : 
     886            0 :          s% need_to_setvars = .true.
     887              : 
     888              :       end subroutine set_composition
     889              : 
     890              : 
     891            0 :       subroutine set_standard_composition( &
     892              :             s, species, h1, h2, he3, he4, which_zfracs, &
     893              :             dump_missing_into_heaviest, ierr)
     894              :          type (star_info), pointer :: s
     895              :          integer, intent(in) :: species
     896              :          real(dp), intent(in) :: h1, h2, he3, he4  ! mass fractions
     897              :          integer, intent(in) :: which_zfracs  ! defined in chem_def. e.g., GS98_zfracs
     898              :          logical, intent(in) :: dump_missing_into_heaviest
     899              :          integer, intent(out) :: ierr
     900            0 :          real(dp) :: xa(species)
     901              :          ierr = 0
     902              :          call get_xa_for_standard_metals(s, &
     903              :             species, s% chem_id, s% net_iso, h1, h2, he3, he4, which_zfracs, &
     904            0 :             dump_missing_into_heaviest, xa, ierr)
     905            0 :          if (ierr /= 0) return
     906            0 :          call set_uniform_composition(s% id, species, xa, ierr)
     907            0 :       end subroutine set_standard_composition
     908              : 
     909              : 
     910            0 :       subroutine get_xa_for_accretion(s, xa, ierr)
     911              :          use chem_lib, only: chem_get_iso_id
     912              :          type (star_info), pointer :: s
     913              :          real(dp) :: xa(:)  ! (species)
     914              :          integer, intent(out) :: ierr
     915              :          integer :: j, i, species, cid
     916              :          include 'formats'
     917            0 :          ierr = 0
     918            0 :          species = s% species
     919            0 :          if (s% accrete_given_mass_fractions) then
     920            0 :             xa(1:species) = 0
     921            0 :             do j=1,s% num_accretion_species
     922            0 :                if (len_trim(s% accretion_species_id(j)) == 0) cycle
     923            0 :                cid = chem_get_iso_id(s% accretion_species_id(j))
     924            0 :                if (cid <= 0) cycle
     925            0 :                i = s% net_iso(cid)
     926            0 :                if (i == 0) cycle
     927            0 :                xa(i) = s% accretion_species_xa(j)
     928              :             end do
     929            0 :             if (abs(1d0 - sum(xa(1:species))) > 1d-2) then
     930              :                write(*,'(a)') &
     931            0 :                   'get_xa_for_accretion: accretion species mass fractions do not add to 1'
     932            0 :                write(*,1) 'sum(xa(1:species))', sum(xa(1:species))
     933            0 :                do j=1,s% num_accretion_species
     934            0 :                   write(*,2) trim(s% accretion_species_id(j)), j, xa(j)
     935              :                end do
     936            0 :                ierr = -1
     937            0 :                return
     938              :             end if
     939            0 :             xa(1:species) = xa(1:species)/sum(xa(1:species))
     940              :             return
     941              :          end if
     942              :          call get_xa_for_standard_metals(s, &
     943              :             s% species, s% chem_id, s% net_iso, &
     944              :             s% accretion_h1, s% accretion_h2, s% accretion_he3, s% accretion_he4, &
     945              :             s% accretion_zfracs, &
     946            0 :             s% accretion_dump_missing_metals_into_heaviest, xa, ierr)
     947            0 :       end subroutine get_xa_for_accretion
     948              : 
     949              : 
     950            0 :       subroutine do_change_to_xa_for_accretion(id, nzlo_in, nzhi_in, ierr)
     951              :          integer, intent(in) :: id
     952              :          integer, intent(in) :: nzlo_in, nzhi_in
     953              :          integer, intent(out) :: ierr
     954              :          integer :: j, k, species
     955            0 :          real(dp), pointer :: xa(:)  ! (species)
     956              :          type (star_info), pointer :: s
     957              :          integer :: nzlo, nzhi
     958              :          include 'formats'
     959              :          ierr = 0
     960            0 :          call get_star_ptr(id, s, ierr)
     961            0 :          if (ierr /= 0) return
     962            0 :          species = s% species
     963            0 :          nzlo = nzlo_in
     964            0 :          nzhi = nzhi_in
     965            0 :          if (nzlo < 1) nzlo = 1
     966            0 :          if (nzhi < 1 ) nzhi = s% nz
     967            0 :          allocate(xa(species))
     968            0 :          if (s% accrete_same_as_surface) then
     969            0 :             do j=1,species
     970            0 :                xa(j) = s% xa(j,1)
     971              :             end do
     972              :          else
     973            0 :             call get_xa_for_accretion(s, xa, ierr)
     974            0 :             if (ierr /= 0) then
     975            0 :                s% retry_message = 'get_xa_for_accretion failed in change_to_xa_for_accretion'
     976            0 :                if (s% report_ierr) write(*, *) s% retry_message
     977            0 :                deallocate(xa)
     978            0 :                return
     979              :             end if
     980              :          end if
     981            0 :          do k=nzlo,min(s% nz,nzhi)
     982            0 :             do j=1,species
     983            0 :                s% xa(j,k) = xa(j)
     984              :             end do
     985              :          end do
     986            0 :          deallocate(xa)
     987            0 :          s% need_to_setvars = .true.
     988            0 :       end subroutine do_change_to_xa_for_accretion
     989              : 
     990              : 
     991            0 :       subroutine get_xa_for_standard_metals( &
     992            0 :             s, species, chem_id, net_iso, h1_in, h2_in, he3_in, he4_in, which_zfracs, &
     993            0 :             dump_missing_into_heaviest, xa, ierr)
     994              :          use chem_def
     995              :          type (star_info), pointer :: s
     996              :          integer, intent(in) :: species, chem_id(:), net_iso(:), which_zfracs
     997              :          real(dp), intent(in) :: h1_in, h2_in, he3_in, he4_in
     998              :          logical, intent(in) :: dump_missing_into_heaviest
     999              :          real(dp) :: xa(:)  ! (species)
    1000              :          integer, intent(out) :: ierr
    1001            0 :          real(dp) :: zfrac(num_chem_elements), Z, h1, h2, he3, he4
    1002              :          integer :: i
    1003              :          include 'formats'
    1004            0 :          ierr = 0
    1005            0 :          h1 = h1_in; h2 = h2_in; he3 = he3_in; he4 = he4_in
    1006            0 :          select case(which_zfracs)
    1007              :             case (AG89_zfracs)
    1008            0 :                zfrac(:) = AG89_element_zfrac(:)
    1009              :             case (GN93_zfracs)
    1010            0 :                zfrac(:) = GN93_element_zfrac(:)
    1011              :             case (GS98_zfracs)
    1012            0 :                zfrac(:) = GS98_element_zfrac(:)
    1013              :             case (L03_zfracs)
    1014            0 :                zfrac(:) = L03_element_zfrac(:)
    1015              :             case (AGS05_zfracs)
    1016            0 :                zfrac(:) = AGS05_element_zfrac(:)
    1017              :             case (AGSS09_zfracs)
    1018            0 :                zfrac(:) = AGSS09_element_zfrac(:)
    1019              :             case (L09_zfracs)
    1020            0 :                zfrac(:) = L09_element_zfrac(:)
    1021              :             case (A09_Prz_zfracs)
    1022            0 :                zfrac(:) = A09_Prz_zfrac(:)
    1023              :             case (MB22_photospheric_zfracs)
    1024            0 :                zfrac(:) = MB22_photospheric_element_zfrac(:)
    1025              :             case (AAG21_photospheric_zfracs)
    1026            0 :                zfrac(:) = AAG21_photospheric_element_zfrac(:)
    1027              :             case (Custom_zfracs)  ! use non-standard values given in controls
    1028            0 :                zfrac(:) = 0
    1029            0 :                zfrac(e_li) = s% z_fraction_li
    1030            0 :                zfrac(e_be) = s% z_fraction_be
    1031            0 :                zfrac(e_b)  = s% z_fraction_b
    1032            0 :                zfrac(e_c)  = s% z_fraction_c
    1033            0 :                zfrac(e_n)  = s% z_fraction_n
    1034            0 :                zfrac(e_o)  = s% z_fraction_o
    1035            0 :                zfrac(e_f)  = s% z_fraction_f
    1036            0 :                zfrac(e_ne) = s% z_fraction_ne
    1037            0 :                zfrac(e_na) = s% z_fraction_na
    1038            0 :                zfrac(e_mg) = s% z_fraction_mg
    1039            0 :                zfrac(e_al) = s% z_fraction_al
    1040            0 :                zfrac(e_si) = s% z_fraction_si
    1041            0 :                zfrac(e_p)  = s% z_fraction_p
    1042            0 :                zfrac(e_s)  = s% z_fraction_s
    1043            0 :                zfrac(e_cl) = s% z_fraction_cl
    1044            0 :                zfrac(e_ar) = s% z_fraction_ar
    1045            0 :                zfrac(e_k)  = s% z_fraction_k
    1046            0 :                zfrac(e_ca) = s% z_fraction_ca
    1047            0 :                zfrac(e_sc) = s% z_fraction_sc
    1048            0 :                zfrac(e_ti) = s% z_fraction_ti
    1049            0 :                zfrac(e_v)  = s% z_fraction_v
    1050            0 :                zfrac(e_cr) = s% z_fraction_cr
    1051            0 :                zfrac(e_mn) = s% z_fraction_mn
    1052            0 :                zfrac(e_fe) = s% z_fraction_fe
    1053            0 :                zfrac(e_co) = s% z_fraction_co
    1054            0 :                zfrac(e_ni) = s% z_fraction_ni
    1055            0 :                zfrac(e_cu) = s% z_fraction_cu
    1056            0 :                zfrac(e_zn) = s% z_fraction_zn
    1057            0 :                if (abs(sum(zfrac)-1) > 1d-6) then
    1058            0 :                   write(*,*) 'bad sum(zfrac) for specified z fractions', sum(zfrac)
    1059            0 :                   ierr = -1
    1060              :                end if
    1061            0 :                do i = 1, size(zfrac, dim=1)
    1062            0 :                   if (zfrac(i) < 0) then
    1063            0 :                      write(*,2) 'zfrac(i)', i, zfrac(i)
    1064            0 :                      ierr = -1
    1065            0 :                      return
    1066              :                   end if
    1067              :                end do
    1068            0 :                zfrac(:) = zfrac(:) / sum(zfrac(:))
    1069              :             case default
    1070            0 :                if (abs(1d0 - (h1 + h2 + he3 + he4)) < 1d-8) then  ! okay -- no metals
    1071            0 :                   if (h1 > he4) then
    1072            0 :                      h1 = max(0d0, min(1d0, 1d0 - (h2 + he3 + he4)))
    1073              :                   else
    1074            0 :                      he4 = max(0d0, min(1d0, 1d0 - (h1 + h2 + he3)))
    1075              :                   end if
    1076            0 :                   zfrac(:) = 0
    1077              :                else
    1078            0 :                   ierr = -1
    1079              :                end if
    1080              :          end select
    1081            0 :          if (ierr /= 0) return
    1082            0 :          Z = max(0d0, min(1d0, 1d0 - (h1 + h2 + he3 + he4)))
    1083              :          call get_xa( &
    1084              :             species, chem_id, net_iso, h1, h2, he3, he4, zfrac, Z, &
    1085            0 :             dump_missing_into_heaviest, xa, ierr)
    1086            0 :          do i=1,species
    1087            0 :             if (xa(i) < 0 .or. is_bad(xa(i))) then
    1088            0 :                write(*,2) 'get_xa_for_standard_metals xa(i)', i, xa(i)
    1089            0 :                ierr = -1
    1090            0 :                return
    1091              :             end if
    1092              :          end do
    1093            0 :       end subroutine get_xa_for_standard_metals
    1094              : 
    1095              : 
    1096            0 :       subroutine get_xa( &
    1097            0 :             species, chem_id, net_iso, h1, h2, he3, he4, zfrac, Zinit, &
    1098            0 :             dump_missing_into_heaviest, xa, ierr)
    1099            0 :          use chem_def
    1100              :          integer, intent(in) :: species, chem_id(:), net_iso(:)
    1101              :          real(dp), intent(in) :: h1, h2, he3, he4, Zinit
    1102              :          real(dp), intent(in) :: zfrac(:)  ! (num_chem_elements)
    1103              :          logical, intent(in) :: dump_missing_into_heaviest
    1104              :          real(dp) :: xa(:)  ! (species)
    1105              :          real(dp), parameter :: tiny = 1d-15
    1106              :          integer, intent(out) :: ierr
    1107              :          include 'formats'
    1108              :          if (h1 < 0 .and. abs(h1)>tiny &
    1109              :              .or. h2 < 0 .and. abs(h2)>tiny &
    1110              :              .or. he3 < 0.and. abs(he3)>tiny &
    1111              :              .or. he4 < 0.and. abs(he4)>tiny &
    1112            0 :              .or.Zinit < 0.and.abs(Zinit)>tiny ) then
    1113            0 :             ierr = -1
    1114            0 :             write(*,*) 'when setting composition, need to provide values for h1, h2, he3, and he4'
    1115            0 :             write(*,*) 'H1=', h1
    1116            0 :             write(*,*) 'H2=', h2
    1117            0 :             write(*,*) 'He3=', he3
    1118            0 :             write(*,*) 'He4=', he4
    1119            0 :             write(*,*) 'Z  =', Zinit
    1120            0 :             return
    1121            0 :          else if ( abs(1d0-(h1+h2+he3+he4+Zinit)) > tiny ) then
    1122            0 :             ierr = -2
    1123            0 :             write(*,1) 'h1', h1
    1124            0 :             write(*,1) 'h2', h2
    1125            0 :             write(*,1) 'he3', he3
    1126            0 :             write(*,1) 'he4', he4
    1127            0 :             write(*,1) 'Zinit', Zinit
    1128            0 :             write(*,*) 'sum of (H1+H2+He3+He4+Z) does not sum to 1: (1-sum)= ', &
    1129            0 :                1d0-(h1+h2+he3+he4+Zinit)
    1130            0 :             call mesa_error(__FILE__,__LINE__,'get_xa')
    1131              :          end if
    1132            0 :          ierr = 0
    1133            0 :          xa(:) = 0
    1134            0 :          if (net_iso(ih2) /= 0) then
    1135            0 :             xa(net_iso(ih2)) = h2
    1136            0 :             xa(net_iso(ih1)) = h1
    1137            0 :          else if (net_iso(ih1) /= 0) then
    1138            0 :             xa(net_iso(ih1)) = h1 + h2
    1139              :          else
    1140            0 :             ierr = -1
    1141            0 :             write(*,*) 'require h1 to be in net'
    1142            0 :             return
    1143              :          end if
    1144            0 :          if (net_iso(ihe3) /= 0) xa(net_iso(ihe3)) = he3
    1145            0 :          if (net_iso(ihe4) /= 0) xa(net_iso(ihe4)) = he4
    1146              :          call adjust_z_fractions( &
    1147              :             species, chem_id, 1d0-(h1+h2+he3+he4), zfrac, &
    1148            0 :             dump_missing_into_heaviest, xa, ierr)
    1149            0 :          xa(:) = xa(:)/sum(xa)
    1150            0 :       end subroutine get_xa
    1151              : 
    1152              : 
    1153            0 :       subroutine adjust_z_fractions( &
    1154            0 :             species, chem_id, ztotal, zfrac, dump_missing_into_heaviest, xa, ierr)
    1155            0 :          use chem_def
    1156              :          use chem_lib, only: lodders03_element_atom_percent
    1157              :          integer, intent(in) :: species, chem_id(:)  ! (species)
    1158              :          real(dp), intent(in) :: ztotal
    1159              :          real(dp), intent(in) :: zfrac(:)  ! (num_chem_elements)
    1160              :          logical, intent(in) :: dump_missing_into_heaviest
    1161              :          real(dp) :: xa(:)  ! (species) h & he not touched
    1162              :          integer, intent(out) :: ierr
    1163              : 
    1164            0 :          integer :: i, j, cid, cid2, element_id, jskip, Z(species)
    1165            0 :          real(dp) :: new_xa(species), frac, frac_sum, iso_frac, zsum
    1166              : 
    1167              :          include 'formats'
    1168              : 
    1169            0 :          ierr = 0
    1170            0 :          new_xa(:) = 0
    1171              : 
    1172            0 :          if (dump_missing_into_heaviest) then
    1173            0 :             jskip = maxloc(chem_isos% W(chem_id(:)),dim=1)  ! find the heaviest
    1174              :          else
    1175              :             jskip = 0
    1176              :          end if
    1177              : 
    1178            0 :          do j=1,species
    1179            0 :             Z(j) = chem_isos% Z(chem_id(j))
    1180              :          end do
    1181              : 
    1182            0 :          do j=1,species
    1183            0 :             if (j == jskip) cycle
    1184            0 :             if (Z(j) <= 2) cycle
    1185            0 :             cid = chem_id(j)
    1186              :             ! multiply lodders' number fractions by chem_isos% A since want fractions by mass
    1187            0 :             frac = 1d-2*lodders03_element_atom_percent(chem_isos% name(cid))*chem_isos% W(cid)
    1188            0 :             if (frac == 0) cycle
    1189              :             frac_sum = 0
    1190            0 :             do i=1,species
    1191            0 :                if (Z(i) /= Z(j)) cycle
    1192            0 :                cid2 = chem_id(i)
    1193              :                frac_sum = frac_sum + &
    1194            0 :                   1d-2*lodders03_element_atom_percent(chem_isos% name(cid2))*chem_isos% W(cid2)
    1195              :             end do
    1196            0 :             element_id = Z(j)  ! element index equals number of protons
    1197            0 :             iso_frac = frac/frac_sum  ! this iso is iso_frac of the element abundance by mass
    1198            0 :             new_xa(j) = ztotal*zfrac(element_id)*iso_frac
    1199              :          end do
    1200              : 
    1201            0 :          if (jskip > 0) then
    1202              :             ! put the missing metals into jskip
    1203            0 :             new_xa(jskip) = max(0d0, ztotal-sum(new_xa(:)))
    1204            0 :             do j=1,species
    1205            0 :                if (j == jskip) cycle
    1206            0 :                if (Z(j) <= 2) cycle
    1207            0 :                xa(j) = new_xa(j)
    1208              :             end do
    1209            0 :             xa(jskip) = new_xa(jskip)
    1210              :          else  ! renormalize all of the metals
    1211            0 :             zsum = sum(new_xa(:))  ! only have metals in new_xa
    1212            0 :             if (zsum > 0d0) then
    1213            0 :                do j=1,species
    1214            0 :                   if (Z(j) <= 2) cycle
    1215            0 :                   xa(j) = new_xa(j)*ztotal/zsum
    1216              :                end do
    1217              :             end if
    1218              :          end if
    1219              : 
    1220            0 :       end subroutine adjust_z_fractions
    1221              : 
    1222              : 
    1223            0 :       subroutine set_z(s, new_z, nzlo, nzhi, ierr)
    1224            0 :          use net_lib, only:clean_up_fractions
    1225              :          use star_utils, only: eval_current_z
    1226              :          type (star_info), pointer :: s
    1227              :          real(dp), intent(in) :: new_z
    1228              :          integer, intent(in) :: nzlo, nzhi
    1229              :          integer, intent(out) :: ierr
    1230              : 
    1231              :          integer :: nz, h1, he3, he4, species
    1232            0 :          real(dp) :: frac_z, current_z, initial_z
    1233              :          real(dp), parameter :: max_sum_abs = 10d0
    1234              :          real(dp), parameter :: xsum_tol = 1d-2
    1235              : 
    1236              :          include 'formats'
    1237              : 
    1238            0 :          ierr = 0
    1239              : 
    1240            0 :          if (nzlo > nzhi) then
    1241            0 :             ierr = -1; return
    1242              :          end if
    1243              : 
    1244            0 :          nz = s% nz
    1245            0 :          species = s% species
    1246            0 :          h1 = s% net_iso(ih1)
    1247            0 :          he3 = s% net_iso(ihe3)
    1248            0 :          he4 = s% net_iso(ihe4)
    1249              : 
    1250            0 :          call clean_up_fractions(1, nz, species, nz, s% xa, max_sum_abs, xsum_tol, ierr)
    1251            0 :          if (ierr /= 0) return
    1252              : 
    1253            0 :          current_z = eval_current_z(s, nzlo, nzhi, ierr)
    1254            0 :          initial_z = current_z
    1255              : 
    1256            0 :          if (current_z <= 0 .and. new_z > 0) then
    1257            0 :             ierr = -1
    1258            0 :             return
    1259              :          end if
    1260            0 :          frac_z = new_z/current_z
    1261              : 
    1262            0 :          if (abs(1-frac_z) < 1d-20) return
    1263              : 
    1264            0 :          call convert
    1265            0 :          if (ierr /= 0) return
    1266              : 
    1267              :          ! check
    1268            0 :          current_z = eval_current_z(s, nzlo, nzhi, ierr)
    1269              : 
    1270            0 :          if (abs(current_z-new_z) > 1d-8 .or. is_bad(current_z)) then
    1271            0 :             ierr = -1
    1272            0 :             s% retry_message = 'set_z failed'
    1273            0 :             if (s% report_ierr) then
    1274            0 :                write(*, *) 'set_z failed'
    1275            0 :                write(*, 1) 'initial_z', initial_z
    1276            0 :                write(*, 1) 'requested new_z', new_z
    1277            0 :                write(*, 1) 'actual current_z', current_z
    1278            0 :                write(*, *)
    1279            0 :                write(*, 1) 'requested/initial', new_z/initial_z
    1280            0 :                write(*, 1) 'requested/final', new_z/current_z
    1281            0 :                write(*, *)
    1282              :             end if
    1283            0 :             if (s% stop_for_bad_nums) then
    1284            0 :                write(*, 1) 'initial_z', initial_z
    1285            0 :                write(*, 1) 'requested new_z', new_z
    1286            0 :                write(*, 1) 'actual current_z', current_z
    1287            0 :                call mesa_error(__FILE__,__LINE__,'set_z')
    1288              :             end if
    1289              :          end if
    1290              : 
    1291            0 :          if (s% doing_first_model_of_run) then
    1292            0 :             s% initial_z = new_z
    1293            0 :             write(*,1) 's% initial_z =', new_z
    1294              :          end if
    1295              : 
    1296            0 :          s% need_to_setvars = .true.
    1297              : 
    1298              : 
    1299              :          contains
    1300              : 
    1301            0 :          subroutine convert
    1302              :             integer :: i, k
    1303            0 :             real(dp) :: old_z, old_xy, sumfracs, sum_z, frac_xy
    1304              :             include 'formats'
    1305            0 :             do k=nzlo, nzhi
    1306            0 :                old_z = 0; old_xy = 0
    1307            0 :                do i=species, 1, -1
    1308            0 :                   if (i==h1 .or. i==he3 .or. i==he4) then
    1309            0 :                      old_xy = old_xy + s% xa(i, k)
    1310              :                   end if
    1311              :                end do
    1312            0 :                old_z = 1 - old_xy
    1313            0 :                sum_z = 0
    1314            0 :                do i=species, 1, -1
    1315            0 :                   if (i==h1 .or. i==he3 .or. i==he4) cycle
    1316            0 :                   s% xa(i, k) = s% xa(i, k)*frac_z
    1317            0 :                   sum_z = sum_z + s% xa(i, k)
    1318              :                end do
    1319              :                ! sum_z is the new z for this cell
    1320              :                ! modify x and y to make mass fractions sum to 1
    1321            0 :                if (old_z < 1) then
    1322            0 :                   frac_xy = (1 - old_z*frac_z)/old_xy
    1323            0 :                   s% xa(h1, k) = s% xa(h1, k)*frac_xy
    1324            0 :                   if (he3 /= 0) s% xa(he3, k) = s% xa(he3, k)*frac_xy
    1325            0 :                   s% xa(he4, k) = s% xa(he4, k)*frac_xy
    1326              :                else
    1327            0 :                   s% xa(h1, k) = (1-sum_z)/2
    1328            0 :                   if (he3 /= 0) s% xa(he3, k) = 0
    1329            0 :                   s% xa(he4, k) = (1-sum_z)/2
    1330              :                end if
    1331            0 :                sumfracs = 0
    1332            0 :                do i=species, 1, -1
    1333            0 :                   sumfracs = sumfracs + s% xa(i, k)
    1334              :                end do
    1335            0 :                s% xa(1:species, k) = s% xa(1:species, k)/sumfracs
    1336            0 :                do i=1, species
    1337            0 :                   if (is_bad(s% xa(i, k))) then
    1338            0 :                      ierr = -1
    1339            0 :                      s% retry_message = 'set_z failed - bad mass fraction'
    1340            0 :                      if (s% report_ierr) then
    1341            0 :                         write(*,2) 'set_z s% xa(i, k)', k, s% xa(i, k)
    1342              :                      end if
    1343            0 :                      if (s% stop_for_bad_nums) then
    1344            0 :                         write(*,2) 'set_z s% xa(i, k)', k, s% xa(i, k)
    1345            0 :                         call mesa_error(__FILE__,__LINE__,'set_z')
    1346              :                      end if
    1347            0 :                      return
    1348              :                   end if
    1349              :                end do
    1350              :             end do
    1351            0 :          end subroutine convert
    1352              : 
    1353              :       end subroutine set_z
    1354              : 
    1355              : 
    1356            0 :       subroutine do_replace(s, id1, id2, nzlo, nzhi, ierr)
    1357              :          ! replaces species1 by species2
    1358              :          type (star_info), pointer :: s
    1359              :          integer, intent(in) :: id1, id2  ! values are chem_id's such as ihe4
    1360              :          integer, intent(in) :: nzlo, nzhi
    1361              :          integer, intent(out) :: ierr
    1362              : 
    1363              :          integer :: k, nz, species, species1, species2
    1364              : 
    1365            0 :          ierr = 0
    1366            0 :          nz = s% nz
    1367            0 :          species = s% species
    1368            0 :          species1 = s% net_iso(id1)
    1369            0 :          species2 = s% net_iso(id2)
    1370              : 
    1371            0 :          do k=nzlo, nzhi
    1372            0 :             s% xa(species2, k) = s% xa(species1, k) + s% xa(species2, k)
    1373            0 :             s% xa(species1, k) = 0
    1374              :          end do
    1375              : 
    1376            0 :          s% need_to_setvars = .true.
    1377              : 
    1378            0 :       end subroutine do_replace
    1379              : 
    1380              : 
    1381            0 :       subroutine do_uniform_mix_section(s, species, nzlo_in, nzhi_in, ierr)
    1382              :          type (star_info), pointer :: s
    1383              :          integer, intent(in) :: species, nzlo_in, nzhi_in
    1384              :          integer, intent(out) :: ierr
    1385              :          integer :: j, k, nzlo, nzhi
    1386            0 :          real(dp) :: dqsum, newxa(species), xsum
    1387              :          include 'formats'
    1388            0 :          ierr = 0
    1389            0 :          nzlo = max(1, nzlo_in)
    1390            0 :          nzhi = min(s% nz, nzhi_in)
    1391            0 :          dqsum = sum(s% dq(nzlo:nzhi))
    1392            0 :          do j=1,species
    1393            0 :             newxa(j) = dot_product(s% dq(nzlo:nzhi), s% xa(j,nzlo:nzhi))/dqsum
    1394              :          end do
    1395            0 :          xsum = sum(newxa(:))
    1396            0 :          do j=1,species
    1397            0 :             newxa(j) = newxa(j)/xsum
    1398              :          end do
    1399            0 :          do k=nzlo,nzhi
    1400            0 :             do j=1,species
    1401            0 :                s% xa(j,k) = newxa(j)
    1402              :             end do
    1403              :          end do
    1404            0 :          s% need_to_setvars = .true.
    1405            0 :       end subroutine do_uniform_mix_section
    1406              : 
    1407              : 
    1408            0 :       subroutine do_uniform_mix_envelope_down_to_T(s, T, ierr)
    1409              :          type (star_info), pointer :: s
    1410              :          real(dp), intent(in) :: T
    1411              :          integer, intent(out) :: ierr
    1412              :          integer :: k, kmix
    1413            0 :          ierr = 0
    1414            0 :          if (s% T(1) > T) return
    1415            0 :          kmix = s% nz
    1416            0 :          do k=2,s% nz
    1417            0 :             if (s% T(k) > T) then
    1418            0 :                kmix = k-1
    1419            0 :                exit
    1420              :             end if
    1421              :          end do
    1422            0 :          call do_uniform_mix_section(s, s% species, 1, kmix, ierr)
    1423              :       end subroutine do_uniform_mix_envelope_down_to_T
    1424              : 
    1425              : 
    1426            0 :       subroutine do_set_abundance(s, chem_id, new_frac, nzlo, nzhi, ierr)
    1427              :          ! set mass fraction of species to new_frac uniformly in cells nzlo to nzhi
    1428              :          type (star_info), pointer :: s
    1429              :          integer, intent(in) :: chem_id
    1430              :          real(dp), intent(in) :: new_frac
    1431              :          integer, intent(in) :: nzlo, nzhi
    1432              :          integer, intent(out) :: ierr
    1433              : 
    1434              :          integer :: k, j, i, nz, species
    1435            0 :          real(dp) :: old_frac, rescale
    1436              : 
    1437            0 :          ierr = 0
    1438            0 :          nz = s% nz
    1439            0 :          species = s% species
    1440            0 :          j = s% net_iso(chem_id)
    1441            0 :          if (j == 0) then
    1442            0 :             write(*,*) 'do_set_abundance: failed to find requested iso in current net'
    1443            0 :             ierr = -1
    1444            0 :             return
    1445              :          end if
    1446              : 
    1447            0 :          do k=nzlo, nzhi
    1448            0 :             old_frac = s% xa(j, k)
    1449            0 :             s% xa(j, k) = new_frac
    1450            0 :             if (1d0-old_frac > 1d-10) then
    1451            0 :                rescale = (1-new_frac)/(1-old_frac)
    1452            0 :                do i=1, species
    1453            0 :                   if (i==j) cycle
    1454            0 :                   s% xa(i, k) = rescale*s% xa(i, k)
    1455              :                end do
    1456              :             else
    1457            0 :                rescale = (1-new_frac)/(species-1)
    1458            0 :                do i=1, species
    1459            0 :                   if (i==j) cycle
    1460            0 :                   s% xa(i, k) = rescale
    1461              :                end do
    1462              :             end if
    1463              :          end do
    1464            0 :          s% need_to_setvars = .true.
    1465              : 
    1466              :       end subroutine do_set_abundance
    1467              : 
    1468              :       end module adjust_xyz
        

Generated by: LCOV version 2.0-1