LCOV - code coverage report
Current view: top level - net/private - net_burn.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.1 % 168 153
Test Date: 2025-07-29 08:23:51 Functions: 100.0 % 5 5

            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 net_burn
      21              :       use const_def, only: dp, Qconv
      22              :       use math_lib
      23              :       use chem_def
      24              :       use net_def
      25              :       use utils_lib, only: is_bad,fill_with_NaNs,fill_with_NaNs_2D
      26              :       use net_burn_support, only: netint
      27              :       use net_approx21, only : num_reactions_func => num_reactions
      28              : 
      29              :       implicit none
      30              : 
      31              :       !logical, parameter :: use_ludcmp = .true.
      32              :       logical, parameter :: use_ludcmp = .false.
      33              : 
      34              :       !logical, parameter :: show_mesa_rates = .true.
      35              :       logical, parameter :: show_mesa_rates = .false.
      36              : 
      37              :       !logical, parameter :: report_ierr = .true.
      38              :       logical, parameter :: report_ierr = .false.
      39              : 
      40              :       contains
      41              : 
      42            2 :       subroutine get_pointers( &
      43              :             g, species, num_reactions, &
      44              :             dratdumdy1, dratdumdy2, dens_dfdy, dmat, i, ierr)
      45              :          use net_approx21, only: approx21_nrat
      46              :          type (Net_General_Info), pointer :: g
      47              :          integer, intent(in) :: species, num_reactions
      48              :          real(dp), allocatable, dimension(:) :: dratdumdy1, dratdumdy2
      49              :          real(dp), allocatable, dimension(:,:) :: dens_dfdy, dmat
      50              :          integer, intent(inout) :: i
      51              :          integer, intent(out) :: ierr
      52              :          integer :: sz
      53              :          include 'formats'
      54            2 :          ierr = 0
      55              : 
      56            2 :          sz = num_reactions
      57            2 :          if (g% doing_approx21) sz = num_reactions_func(g% add_co56_to_approx21)
      58              : 
      59            2 :          allocate(dratdumdy1(1:sz))
      60            2 :          allocate(dratdumdy2(1:sz))
      61              : 
      62            4 :          allocate(dens_dfdy(1:species,1:species))
      63            2 :          allocate(dmat(1:species,1:species))
      64              : 
      65            2 :          if (g% fill_arrays_with_nans) then
      66            0 :             call fill_with_NaNs(dratdumdy1)
      67            0 :             call fill_with_NaNs(dratdumdy2)
      68            0 :             call fill_with_NaNs_2D(dens_dfdy)
      69            0 :             call fill_with_NaNs_2D(dmat)
      70              :          end if
      71              : 
      72            2 :       end subroutine get_pointers
      73              : 
      74              : 
      75            2 :       subroutine burn_1_zone( &
      76            2 :             net_handle, eos_handle, species, num_reactions, t_start, t_end, starting_x, &
      77              :             ntimes, times, log10Ts_f1, log10Rhos_f1, etas_f1, dxdt_source_term, &
      78              :             rate_factors, weak_rate_factor, &
      79              :             reaction_Qs, reaction_neuQs, &
      80              :             screening_mode,  &
      81              :             stptry_in, max_steps, eps, odescal, &
      82              :             use_pivoting, trace, burn_dbg, burner_finish_substep, &
      83            2 :             ending_x, eps_nuc_categories, avg_eps_nuc, eps_neu_total, &
      84              :             nfcn, njac, nstep, naccpt, nrejct, ierr)
      85            2 :          use num_def
      86              :          use num_lib
      87              :          use mtx_lib
      88              :          use mtx_def
      89              :          use rates_def, only: rates_reaction_id_max, reaction_Name, reaction_categories
      90              :          use rates_lib, only: rates_reaction_id
      91              :          use net_initialize, only: setup_net_info
      92              :          use chem_lib, only: basic_composition_info, get_Q
      93              :          use net_approx21, only: approx21_nrat
      94              : 
      95              :          integer, intent(in) :: net_handle, eos_handle
      96              :          integer, intent(in) :: species
      97              :          integer, intent(in) :: num_reactions
      98              :          real(dp), intent(in) :: t_start, t_end, starting_x(:)  ! (species)
      99              :          integer, intent(in) :: ntimes  ! ending time is times(num_times); starting time is 0
     100              :          real(dp), pointer, intent(in) :: times(:)  ! (num_times)
     101              :          real(dp), pointer, intent(in) :: log10Ts_f1(:)
     102              :             ! =(4,numtimes) interpolant for log10T(time)
     103              :          real(dp), pointer, intent(in) :: log10Rhos_f1(:)
     104              :             ! =(4,numtimes) interpolant for log10Rho(time)
     105              :          real(dp), pointer, intent(in) :: etas_f1(:)
     106              :             ! =(4,numtimes) interpolant for eta(time)
     107              :          real(dp), pointer, intent(in) :: dxdt_source_term(:)
     108              :             ! (species)  or null if no source term.
     109              :          real(dp), intent(in), pointer :: rate_factors(:)  ! (num_reactions)
     110              :          real(dp), intent(in) :: weak_rate_factor
     111              :          real(dp), pointer, intent(in) :: reaction_Qs(:)  ! (rates_reaction_id_max)
     112              :          real(dp), pointer, intent(in) :: reaction_neuQs(:)  ! (rates_reaction_id_max)
     113              :          integer, intent(in) :: screening_mode  ! see screen_def
     114              :          real(dp), intent(in) :: stptry_in
     115              :          integer, intent(in) :: max_steps  ! maximal number of allowed steps.
     116              :          real(dp), intent(in) :: eps, odescal  ! tolerances.  e.g., set both to 1d-6
     117              :          logical, intent(in) :: use_pivoting
     118              :          logical, intent(in) :: trace, burn_dbg
     119              :          interface
     120              :             include 'burner_finish_substep.inc'
     121              :          end interface
     122              :          real(dp), intent(inout) :: ending_x(:) ! (species)
     123              :          real(dp), intent(inout) :: eps_nuc_categories(:) ! (num_categories)
     124              :          real(dp), intent(out) :: avg_eps_nuc, eps_neu_total
     125              :          integer, intent(out) :: nfcn    ! number of function evaluations
     126              :          integer, intent(out) :: njac    ! number of jacobian evaluations
     127              :          integer, intent(out) :: nstep   ! number of computed steps
     128              :          integer, intent(out) :: naccpt  ! number of accepted steps
     129              :          integer, intent(out) :: nrejct  ! number of rejected steps
     130              :          integer, intent(out) :: ierr
     131              : 
     132              :          type (Net_General_Info), pointer :: g
     133              :          integer :: ijac, lrd, lid, lout, i, j, ir, idid, sz
     134              :          logical :: okay, have_set_rate_screened
     135            4 :          real(dp) :: temp, rho, eta, lgT, lgRho, r, prev_lgRho, prev_lgT
     136              : 
     137              :          integer :: stpmax, imax_dydx, nstp
     138              :          real(dp) :: &
     139            2 :             h, start, stptry, stpmin, stopp, max_dydx, abs_max_dydx, &
     140           44 :             burn_ergs, dx
     141              : 
     142          132 :          real(dp), dimension(species), target :: starting_y_a, ending_y_a, save_x_a
     143            2 :          real(dp), dimension(:), pointer :: starting_y, ending_y, save_x
     144            2 :          real(dp), dimension(:), allocatable :: dratdumdy1, dratdumdy2
     145              : 
     146            2 :          real(dp), dimension(:,:), allocatable :: dens_dfdy, dmat
     147              : 
     148            2 :          real(dp) :: xh, xhe, z, abar, zbar, z2bar, z53bar, ye, mass_correction, sumx
     149           44 :          real(dp) :: aion(species)
     150              : 
     151              :          logical :: dbg
     152              : 
     153            2 :          type (Net_Info) :: n
     154              : 
     155              :          integer :: iwork, cid
     156              : 
     157              :          include 'formats'
     158              : 
     159              :          !dbg = .true.
     160            2 :          dbg = burn_dbg
     161              : 
     162            2 :          if (dbg) then
     163            0 :             do i=1,species
     164            0 :                write(*,2) 'starting_x', i, starting_x(i)
     165              :             end do
     166              :          end if
     167              : 
     168            2 :          starting_y => starting_y_a
     169            2 :          ending_y => ending_y_a
     170            2 :          save_x => save_x_a
     171              : 
     172            2 :          have_set_rate_screened = .false.
     173              : 
     174            2 :          lgT = log10Ts_f1(1)
     175            2 :          temp = exp10(lgT)
     176            2 :          lgRho = log10Rhos_f1(1)
     177            2 :          rho = exp10(lgRho)
     178            2 :          eta = etas_f1(1)
     179            2 :          prev_lgT = -1d99
     180            2 :          prev_lgRho = -1d99
     181              : 
     182              :          ierr = 0
     183            2 :          call get_net_ptr(net_handle, g, ierr)
     184            2 :          if (ierr /= 0) then
     185              :             if (report_ierr) write(*,*) 'invalid handle for burn_1_zone'
     186              :             return
     187              :          end if
     188              : 
     189            2 :          if (g% num_isos /= species) then
     190            0 :             write(*,*) 'invalid species', species
     191            0 :             return
     192              :          end if
     193              : 
     194            2 :          if (g% num_reactions /= num_reactions) then
     195            0 :             write(*,*) 'invalid num_reactions', num_reactions
     196            0 :             return
     197              :          end if
     198              : 
     199            2 :          nfcn = 0
     200            2 :          njac = 0
     201            2 :          nstep = 0
     202            2 :          naccpt = 0
     203            2 :          nrejct = 0
     204              : 
     205           44 :          do i=1,species
     206           42 :             cid = g% chem_id(i)
     207           42 :             if (cid < 0) cid = g% approx21_ye_iso
     208           42 :             aion(i) = chem_isos% Z_plus_N(cid)
     209           42 :             save_x(i) = starting_x(i)
     210           42 :             ending_x(i) = starting_x(i)
     211           42 :             starting_y(i) = starting_x(i)/aion(i)
     212           44 :             ending_y(i) = starting_y(i)
     213              :          end do
     214              : 
     215            2 :          start = t_start
     216            2 :          stptry = stptry_in
     217            2 :          if (stptry == 0d0) stptry = t_end
     218              : 
     219              :          !write(*,1) 'stptry', stptry
     220              : 
     221            2 :          stpmin = min(t_end*1d-20,stptry*1d-6)
     222            2 :          stopp = t_end
     223            2 :          stpmax = max_steps
     224              : 
     225            2 :          n% screening_mode = screening_mode
     226            2 :          n% g => g
     227              : 
     228            2 :          if (dbg) write(*,*) 'call setup_net_info'
     229            2 :          call setup_net_info(n)
     230            2 :          if (dbg) write(*,*) 'done setup_net_info'
     231              : 
     232            0 :          if (dbg) write(*,*) 'call get_pointers'
     233              :          call get_pointers( &
     234              :             g, species, num_reactions, &
     235            2 :             dratdumdy1, dratdumdy2, dens_dfdy, dmat, iwork, ierr)
     236            2 :          if (ierr /= 0) return
     237              : 
     238              :          call basic_composition_info( &
     239              :             species, g% chem_id, starting_x, xh, xhe, z, &
     240            2 :             abar, zbar, z2bar, z53bar, ye, mass_correction, sumx)
     241              : 
     242            2 :          stptry = max(start * 1.0d-10,1.0d-16)
     243            2 :          stpmin = stptry * 1.0d-12
     244              : 
     245            2 :          if (dbg) write(*,*) 'call netint'
     246              :          call netint( &
     247              :             start,stptry,stpmin,max_steps,stopp,ending_y, &
     248              :             eps,species,species,naccpt,nrejct,nstep,odescal,dens_dfdy,dmat, &
     249            2 :             burner_derivs,burner_jakob,burner_finish_substep,ierr)
     250            2 :          if (dbg) write(*,*) 'done netint'
     251            2 :          if (ierr /= 0) then
     252              :             return
     253              :             !write(*,*) 'netint ierr'
     254              :             !stop
     255              :          end if
     256              : 
     257           44 :          do i=1,species
     258           44 :             ending_x(i) = ending_y(i)*aion(i)
     259              :          end do
     260              : 
     261              :          ! set burn_ergs according to change in abundances
     262            2 :          burn_ergs = 0
     263           44 :          do i=1,species
     264           42 :             ending_x(i) = ending_y(i)*aion(i)
     265           42 :             dx = ending_x(i) - save_x(i)
     266              :             !write(*,2) 'dx aion end_x', i, dx, aion(i), ending_x(i)
     267           42 :             cid = g% chem_id(i)
     268              :             burn_ergs = burn_ergs + &
     269           44 :                (get_Q(chem_isos,cid))*dx/chem_isos% Z_plus_N(cid)
     270              :          end do
     271            2 :          burn_ergs = burn_ergs*Qconv
     272              :          !write(*,1) 'burn_ergs', burn_ergs
     273            4 :          avg_eps_nuc = burn_ergs/(t_end - t_start) - eps_neu_total
     274              : 
     275              :       contains
     276              : 
     277         3062 :          subroutine burner_derivs(x,y,f,species,ierr)
     278              :             integer, intent(in) :: species
     279              :             real(dp) :: x, y(:), f(:)
     280              :             integer, intent(out) :: ierr
     281              :             integer, parameter :: ld_dfdx = 0
     282         3062 :             real(dp), target :: dfdx_arry(ld_dfdx,species)
     283              :             real(dp), pointer :: dfdx(:,:)
     284              :             real(dp) :: dxdt_sum, dxdt_sum_approx21, &
     285              :                Z_plus_N, xsum, r, r1, r2
     286              :             integer :: i, ir, ci, j, k, ibad
     287              :             logical :: okay
     288              : 
     289              :             real(dp), target :: f21_a(species)
     290              :             real(dp), pointer :: f21(:)
     291              : 
     292              :             include 'formats'
     293              : 
     294              :             ierr = 0
     295         3062 :             nfcn = nfcn + 1
     296         3062 :             dfdx => dfdx_arry
     297         3062 :             call jakob_or_derivs(x,y,f,dfdx,ierr)
     298         3062 :             if (ierr /= 0) return
     299              : 
     300            2 :          end subroutine burner_derivs
     301              : 
     302           54 :          subroutine burner_jakob(x,y,dfdy,species,ierr)
     303              :             integer, intent(in) :: species
     304              :             real(dp) :: x, y(:)
     305              :             real(dp) :: dfdy(:,:)
     306              :             integer, intent(out) :: ierr
     307              :             real(dp), target :: f_arry(0)
     308              :             real(dp), pointer :: f(:)
     309              : 
     310              :             real(dp) :: Z_plus_N, df_t, df_m
     311              :             integer :: i, ci, j, cj
     312              :             logical :: okay
     313              :             include 'formats'
     314              : 
     315              :             ierr = 0
     316           54 :             njac = njac + 1
     317           54 :             f => f_arry
     318              : 
     319           54 :             call jakob_or_derivs(x,y,f,dfdy,ierr)
     320           54 :             if (ierr /= 0) return
     321              : 
     322              :          end subroutine burner_jakob
     323              : 
     324         3116 :          subroutine jakob_or_derivs(time,y,f,dfdy,ierr)
     325              :             use chem_lib, only: basic_composition_info
     326              :             use chem_def, only: chem_isos, num_categories, category_name, ih1
     327              :             use net_eval, only: eval_net
     328              :             use rates_def, only: rates_reaction_id_max, i_rate, i_rate_dT, i_rate_dRho
     329              :             use interp_1d_lib, only: interp_value
     330              :             use eos_def, only: num_eos_basic_results, num_eos_d_dxa_results, i_eta
     331              :             use eos_lib, only: eosDT_get
     332              : 
     333              :             real(dp) :: time, y(:), f(:)
     334              :             real(dp) :: dfdy(:,:)
     335              :             integer, intent(out) :: ierr
     336              : 
     337         3116 :             real(dp) :: rho, lgRho, T, lgT, rate_limit, rat, dratdt, dratdd
     338         3116 :             real(dp) :: eta, d_eta_dlnT, d_eta_dlnRho
     339         3116 :             real(dp) :: eps_nuc
     340         3116 :             real(dp) :: d_eps_nuc_dT
     341         3116 :             real(dp) :: d_eps_nuc_dRho
     342        68552 :             real(dp) :: d_eps_nuc_dx(species)
     343        68552 :             real(dp) :: dxdt(species)
     344        68552 :             real(dp) :: d_dxdt_dRho(species)
     345        68552 :             real(dp) :: d_dxdt_dT(species)
     346      1442708 :             real(dp) :: d_dxdt_dx(species, species)
     347              : 
     348              :             logical :: rates_only, dxdt_only, okay
     349              :             integer :: i, j, k, ir
     350              : 
     351         3116 :             real(dp), pointer, dimension(:) :: actual_Qs, actual_neuQs
     352         3116 :             real(dp) :: xsum
     353         3116 :             logical, pointer :: from_weaklib(:)
     354              : 
     355      1511260 :             real(dp), target :: x_a(species), dfdx_a(species,species)
     356         3116 :             real(dp), pointer :: x(:), dfdx(:,:)
     357              : 
     358       249280 :             real(dp), dimension(num_eos_basic_results) :: res, d_dlnd, d_dlnT
     359       199424 :             real(dp) :: d_dxa(num_eos_d_dxa_results,species)
     360              : 
     361              :             include 'formats'
     362              : 
     363         3116 :             ierr = 0
     364              : 
     365         3116 :             x => x_a
     366         3116 :             dfdx => dfdx_a
     367              : 
     368         3116 :             actual_Qs => null()
     369         3116 :             actual_neuQs => null()
     370         3116 :             from_weaklib => null()
     371              : 
     372         3116 :             if (ntimes == 1) then
     373              : 
     374            0 :                lgT = log10Ts_f1(1)
     375            0 :                lgRho = log10Rhos_f1(1)
     376              : 
     377              :             else
     378              : 
     379         3116 :                call interp_value(times, ntimes, log10Ts_f1, time, lgT, ierr)
     380         3116 :                if (ierr /= 0) then
     381              :                   if (report_ierr) &
     382              :                      write(*,1) 'interp_value for lgT failed in jakob for 1 zone burn', time
     383              :                   return
     384              :                end if
     385              : 
     386         3116 :                call interp_value(times, ntimes, log10Rhos_f1, time, lgRho, ierr)
     387         3116 :                if (ierr /= 0) then
     388              :                   if (report_ierr) &
     389              :                      write(*,1) 'interp_value for lgRho failed in jakob for 1 zone burn', time
     390              :                   return
     391              :                end if
     392              : 
     393              :             end if
     394              : 
     395         3116 :             xsum = 0
     396        68552 :             do i=1,species
     397        65436 :                if (is_bad(y(i))) then
     398            0 :                   ierr = -1
     399              :                   if (report_ierr) &
     400              :                      write(*,2) 'net_burn failed in jakob_or_derivs: bad y(i) lgT lgRho', i, y(i), lgT, lgRho
     401            0 :                   return
     402              :                   stop
     403              :                end if
     404        65436 :                y(i) = min(1.0d0, max(y(i),1.0d-30))
     405        65436 :                x(i) = y(i)*aion(i)
     406        68552 :                xsum = xsum + x(i)
     407              :             end do
     408         3116 :             if (trace .and. xsum > 2) write(*,*) 'sum_x, time', xsum, time
     409              : 
     410         3116 :             rho = exp10(lgRho)
     411         3116 :             T = exp10(lgT)
     412              : 
     413              :             call basic_composition_info( &
     414              :                species, g% chem_id, x, xh, xhe, z, &
     415         3116 :                abar, zbar, z2bar, z53bar, ye, mass_correction, sumx)
     416              : 
     417              : 
     418              :             call eosDT_get( &
     419              :                eos_handle, species, g% chem_id, g% net_iso, x, &
     420              :                Rho, lgRho, T, lgT, &
     421         3116 :                res, d_dlnd, d_dlnT, d_dxa, ierr)
     422         3116 :             if (ierr /= 0) then
     423              :                if (report_ierr) write(*,*) 'failed in eosDT_get'
     424              :                return
     425              :             end if
     426         3116 :             eta = res(i_eta)
     427         3116 :             d_eta_dlnT = d_dlnT(i_eta)
     428         3116 :             d_eta_dlnRho = d_dlnd(i_eta)
     429              : 
     430              : 
     431         3116 :             rates_only = .false.
     432         3116 :             dxdt_only = (size(dfdy,dim=1) == 0)
     433              : 
     434              :             call eval_net( &
     435              :                n, g, rates_only, dxdt_only, &
     436              :                species, num_reactions, g% num_wk_reactions, &
     437              :                x, T, lgT, rho, lgRho, &
     438              :                abar, zbar, z2bar, ye, eta, d_eta_dlnT, d_eta_dlnRho, &
     439              :                rate_factors, weak_rate_factor, &
     440              :                reaction_Qs, reaction_neuQs, &
     441              :                eps_nuc, d_eps_nuc_dRho, d_eps_nuc_dT, d_eps_nuc_dx,  &
     442              :                dxdt, d_dxdt_dRho, d_dxdt_dT, d_dxdt_dx,  &
     443              :                screening_mode, &
     444              :                eps_nuc_categories, eps_neu_total, &
     445         3116 :                actual_Qs, actual_neuQs, from_weaklib, .false., ierr)
     446              : 
     447         3116 :             if (size(f,dim=1) > 0) then
     448        67364 :                do j = 1, species
     449        64302 :                   f(j) = dxdt(j)/aion(j)
     450         3062 :                   if (.false. .and. is_bad(f(j))) then
     451              :                      write(*,1) 'x', x
     452              :                      write(*,2) 'f(j)', j, f(j)
     453              :                      call mesa_error(__FILE__,__LINE__,'jakob_or_derivs')
     454              :                   end if
     455              :                end do
     456              :             end if
     457              : 
     458         3116 :             if (.not. dxdt_only) then
     459         1188 :                do j = 1, species
     460        25002 :                   do i = 1, species
     461        23814 :                      dfdy(i,j) = d_dxdt_dx(i,j)*aion(j)/aion(i)
     462         1134 :                      if (.false. .and. is_bad(dfdy(i,j))) then
     463              :                         write(*,1) 'x', x
     464              :                         write(*,3) 'dfdy(i,j)', i, j, dfdy(i,j)
     465              :                         call mesa_error(__FILE__,__LINE__,'jakob_or_derivs')
     466              :                      end if
     467              :                   end do
     468              :                end do
     469              :             end if
     470              : 
     471         6232 :          end subroutine jakob_or_derivs
     472              : 
     473              :       end subroutine burn_1_zone
     474              : 
     475              :       end module net_burn
        

Generated by: LCOV version 2.0-1