LCOV - code coverage report
Current view: top level - rates/private - reaclib_support.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.4 % 370 301
Test Date: 2026-05-14 09:58:24 Functions: 84.2 % 19 16

            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 reaclib_support
      21              :       use rates_def
      22              :       use math_lib
      23              :       use chem_lib
      24              : 
      25              :       implicit none
      26              : 
      27              :       contains
      28              : 
      29              : 
      30            3 :       subroutine set_up_network_information(rates)
      31              :          type(reaction_data), intent(inout) :: rates
      32              :          integer :: current_chapter, i
      33              : 
      34              :          ! set up bookmarks
      35            3 :          current_chapter = 0
      36            3 :          rates% nchapters_included = 0
      37           36 :          rates% chapters_present = 0
      38          102 :          rates% bookmarks = 0
      39       145557 :          do i = 1, rates% nreactions
      40       145557 :             new_chapter : if (rates% chapter(i) /= current_chapter) then
      41              :                ! close out the chapter we just left.
      42           33 :                if (current_chapter /= 0) rates% bookmarks(2,current_chapter) = i-1
      43              :                ! set up information on the new chapter
      44           33 :                current_chapter = rates% chapter(i)
      45           33 :                rates% nchapters_included = rates% nchapters_included + 1
      46           33 :                rates% chapters_present(rates% nchapters_included) = current_chapter
      47           33 :                rates% bookmarks(1,current_chapter) = i
      48              :             end if new_chapter
      49              :          end do
      50              :          ! mark the end of the last chapter
      51            3 :          rates% bookmarks(2,current_chapter) = rates% nreactions
      52            3 :       end subroutine set_up_network_information
      53              : 
      54              : 
      55            3 :       subroutine assign_weights(rates)
      56              :          type(reaction_data), intent(inout) :: rates
      57              :          integer :: i, i1, i2, i3, i4
      58              : 
      59              :          include 'formats'
      60              : 
      61              :          ! check for allocation
      62            3 :          if (.not.associated(rates% weight)) then
      63              :             return
      64              :          end if
      65              : 
      66       145557 :          do i = 1, rates% nreactions
      67       145554 :             i1 = -1; i2 = -2; i3 = -3; i4 = -4
      68       193119 :             select case (rates% chapter(i))
      69              :                case (r_one_one)
      70              :                case (r_one_two)
      71              :                case (r_one_three)
      72              :                case (r_two_one)
      73        47565 :                   i1 = rates% pspecies(1,i)
      74        47565 :                   i2 = rates% pspecies(2,i)
      75              :                case (r_two_two)
      76        45267 :                   i1 = rates% pspecies(1,i)
      77        45267 :                   i2 = rates% pspecies(2,i)
      78              :                case (r_two_three)
      79           69 :                   i1 = rates% pspecies(1,i)
      80           69 :                   i2 = rates% pspecies(2,i)
      81              :                case (r_two_four)
      82           12 :                   i1 = rates% pspecies(1,i)
      83           12 :                   i2 = rates% pspecies(2,i)
      84              :                case (r_three_one)
      85           21 :                   i1 = rates% pspecies(1,i)
      86           21 :                   i2 = rates% pspecies(2,i)
      87           21 :                   i3 = rates% pspecies(3,i)
      88              :                case (r_three_two)
      89            3 :                   i1 = rates% pspecies(1,i)
      90            3 :                   i2 = rates% pspecies(2,i)
      91            3 :                   i3 = rates% pspecies(3,i)
      92              :                case (r_four_two)
      93            6 :                   i1 = rates% pspecies(1,i)
      94            6 :                   i2 = rates% pspecies(2,i)
      95            6 :                   i3 = rates% pspecies(3,i)
      96       145554 :                   i4 = rates% pspecies(4,i)
      97              :                case (r_one_four)
      98              :             end select
      99       145557 :             call set_weight(rates% weight(i))
     100              :          end do
     101              : 
     102       145557 :          do i = 1, rates% nreactions
     103       145554 :             i1 = -1; i2 = -2; i3 = -3; i4 = -4
     104       161877 :             select case (rates% chapter(i))
     105              :                case (r_one_one)
     106              :                case (r_one_two)
     107        16323 :                   i1 = rates% pspecies(2,i)
     108        16323 :                   i2 = rates% pspecies(3,i)
     109              :                case (r_one_three)
     110         7740 :                   i1 = rates% pspecies(2,i)
     111         7740 :                   i2 = rates% pspecies(3,i)
     112         7740 :                   i3 = rates% pspecies(4,i)
     113              :                case (r_two_one)
     114              :                case (r_two_two)
     115        45267 :                   i1 = rates% pspecies(3,i)
     116        45267 :                   i2 = rates% pspecies(4,i)
     117              :                case (r_two_three)
     118           69 :                   i1 = rates% pspecies(3,i)
     119           69 :                   i2 = rates% pspecies(4,i)
     120           69 :                   i3 = rates% pspecies(5,i)
     121              :                case (r_two_four)
     122           12 :                   i1 = rates% pspecies(3,i)
     123           12 :                   i2 = rates% pspecies(4,i)
     124           12 :                   i3 = rates% pspecies(5,i)
     125           12 :                   i4 = rates% pspecies(6,i)
     126              :                case (r_three_one)
     127              :                case (r_three_two)
     128            3 :                   i1 = rates% pspecies(4,i)
     129            3 :                   i2 = rates% pspecies(5,i)
     130              :                case (r_four_two)
     131            6 :                   i1 = rates% pspecies(5,i)
     132            6 :                   i2 = rates% pspecies(6,i)
     133              :                case (r_one_four)
     134         6375 :                   i1 = rates% pspecies(2,i)
     135         6375 :                   i2 = rates% pspecies(3,i)
     136         6375 :                   i3 = rates% pspecies(4,i)
     137       145554 :                   i4 = rates% pspecies(5,i)
     138              :             end select
     139              : 
     140       145557 :             call set_weight(rates% weight_reverse(i))
     141              : 
     142              :          end do
     143              : 
     144              : 
     145              :          contains
     146              : 
     147              : 
     148       291108 :          subroutine set_weight(w)
     149              :             ! nuclei are sorted, so if identical, then are adjacent in list
     150              :             real(dp), intent(out) :: w
     151       291108 :             if (i1 == i2 .and. i2 == i3 .and. i3 == i4) then
     152            0 :                w = 1d0/24d0
     153       291108 :             else if (i2 == i3 .and. (i1 == i2 .or. i3 == i4)) then
     154         6399 :                w = 1d0/6d0
     155       284709 :             else if (i1 == i2) then
     156         7830 :                if (i3 == i4) then
     157            6 :                   w = 1d0/4d0
     158              :                else
     159         7824 :                   w = 1d0/2d0
     160              :                end if
     161       276879 :             else if (i2 == i3 .or. i3 == i4) then
     162           54 :                w = 1d0/2d0
     163              :             else
     164       276825 :                w = 1d0
     165              :             end if
     166       291108 :          end subroutine set_weight
     167              : 
     168              : 
     169              :       end subroutine assign_weights
     170              : 
     171              : 
     172            3 :       subroutine compute_rev_ratio(rates,winvn)
     173              :          use const_def, only : pi, kB=>boltzm, NA=>avo, hbar, &
     174              :             c=>clight, conv=>mev_to_ergs
     175              :          type(reaction_data), intent(inout) :: rates
     176              :          type(nuclide_data), intent(in) :: winvn
     177              :          real(dp) :: mp, mn
     178              :          real(dp),  dimension(max_species_per_reaction) :: g   ! statistical weights of nuclides
     179              :          real(dp), dimension(max_species_per_reaction) :: mass  ! mass no's of nuclides
     180              :          integer, dimension(max_species_per_reaction) :: ps
     181              :          integer :: Ni,No,Nt,i
     182              :          real(dp) :: fac, massfac, sum1, sum2, tmp
     183              : 
     184              : 
     185              :          include 'formats'
     186              : 
     187              :          ! Get these consistently from the isotopes.data file
     188            3 :          mp=winvn%W(chem_get_iso_id('prot'))
     189            3 :          mn=winvn%W(chem_get_iso_id('neut'))
     190              : 
     191            3 :          fac = pow(1d9*kB/(2d0*pi*hbar*hbar*NA),1.5d0)/NA
     192            3 :          massfac = conv*NA/(c*c)
     193              : 
     194       145557 :          rates% weak_mask = 1d0
     195       145557 :          loop_over_rates: do i = 1,rates% nreactions
     196              :             ! weak rates don't have inverses, so set to innocuous values and mask out
     197       145554 :             if (rates% reaction_flag(i) == 'w' .or. rates% reaction_flag(i) == 'e') then
     198        45264 :                rates% weak_mask(i) = 0d0
     199       135792 :                rates% inverse_coefficients(:,i) = [-huge(1d0), 0d0]
     200        45264 :                rates% inverse_exp(i) = 0d0
     201      1131600 :                rates% inverse_part(:,i) = 1d0
     202              :                cycle loop_over_rates
     203              :             end if
     204       100290 :             Ni = Nin(rates% chapter(i))
     205       100290 :             No = Nout(rates% chapter(i))
     206       100290 :             Nt = Ni+No
     207       446646 :             ps(1:Nt) = rates% pspecies(1:Nt,i)
     208       446646 :             g(1:Nt) = 2d0*winvn% spin(ps(1:Nt)) + 1d0
     209              : !           mass(1:Nt) = winvn% Z(ps(1:Nt))*mp + winvn% N(ps(1:Nt))*mn - winvn% binding_energy(ps(1:Nt))*massfac
     210       446646 :             mass(1:Nt) = winvn% W(ps(1:Nt))
     211              : 
     212              :             ! log(prefactor of reverse_ratio)
     213       446646 :             tmp = product(mass(1:Ni))/product(mass(Ni+1:Nt))
     214              :             ! The reactant/product mass ratio always enters with a fixed 3/2 power.
     215              :             ! This follows standard detailed-balance derivations such as
     216              :             ! Fowler et al. 1967 and Smith Clark et al. 2023 Appendix B.
     217       446646 :             rates% inverse_coefficients(1,i) = pow(tmp,1.5d0)*(product(g(1:Ni))/product(g(Ni+1:Nt)))
     218              : 
     219              :             ! -Q/(kB*10**9)
     220       293550 :             sum1 = sum(winvn% binding_energy(ps(1:Ni)))
     221       253386 :             sum2 = sum(winvn% binding_energy(ps(Ni+1:Nt)))
     222       100290 :             rates% inverse_coefficients(2,i) = (sum1-sum2)*conv/kB/1d9
     223              : 
     224              :             ! Reichert et al. 2023 Eq. 21 is the source for the fac^(Ni-No) term,
     225              :             ! but the fixed 3/2 mass exponent above follows Fowler et al. 1967 and
     226              :             ! Smith Clark et al. 2023 Appendix B. The current WinNet implementation
     227              :             ! also uses the fixed 3/2 mass exponent.
     228              :             ! delta_reactants/delta_products is handled in net.
     229              :             ! fac == (mu * kb * T / (2 * pi * hbar^2))^3/2 term without a T^3/2.
     230              :             ! The n-dependent phase-space factor enters as fac^(Ni-No), where
     231              :             ! n = Ni - No. The mass ratio above remains a separate fixed 3/2 term.
     232              : 
     233              :             ! The T makes its way back into our expression inside
     234              :             ! the subroutine compute_some_inverse_lambdas, in reaclib_eval.f90.
     235              :             ! It appears in log form as 1.5d0*rates% inverse_exp(i)*lnT9, where,
     236              :             ! rates% inverse_exp(i) = Ni-No, so,
     237              :             ! 1.5d0*rates% inverse_exp(i)*lnT9 == ln(T^(3n/2)), where n = Ni-No.
     238       100290 :             rates% inverse_exp(i) = Ni - No  ! We use this term in a log() expression in reaclib_eval
     239              : 
     240              :             ! Ni-No should be 0 for non-photo-disintegration reverse rates
     241              :             ! and >=1 for photos's in the reverse channel
     242       100290 :             if (Ni-No /= 0) then
     243              :                ! whether endothermic or exothermic,
     244              :                ! Ni-No handles the sign of Q from rates% inverse_coefficients(2,i)
     245        55023 :                rates% inverse_coefficients(1,i) = rates% inverse_coefficients(1,i) * pow(fac, Ni-No)
     246              :                ! negative values of Q denote endothermic photodisintegrations
     247              :                ! We multiply by fac^|Ni-No| as we want to compute
     248              :                ! rate_photo/rate_forward
     249              : 
     250              :                ! positive values of Q denote exothermic photodisintegrations
     251              :                ! We DIVIDE by fac^|Ni-No| as we want to compute
     252              :                ! rate_reverse/rate_photo
     253              :             else  ! Ni - No = 0
     254        45267 :                rates% inverse_exp(i) = 0  ! ensure this is 0.
     255              :                rates% inverse_coefficients(1,i) = rates% inverse_coefficients(1,i)  ! no point calling pow(fac,0)
     256              :             end if
     257       100290 :             rates% inverse_coefficients(1,i) = log(rates% inverse_coefficients(1,i))
     258              : 
     259              : 
     260              :             rates% inverse_part(:,i) = product(winvn% pfcn(1:npart,ps(1:Ni)),dim=2)/ &
     261     10819797 :                & product(winvn% pfcn(1:npart,ps(Ni+1:Nt)),dim=2)
     262              :          end   do loop_over_rates
     263            3 :       end subroutine compute_rev_ratio
     264              : 
     265            0 :       subroutine do_parse_reaction_handle(handle, num_in, num_out, iso_ids, op, ierr)
     266              :          use chem_def
     267              :          use chem_lib
     268              :          character (len=*), intent(in) :: handle
     269              :          integer, intent(out) :: num_in, num_out
     270              :          integer, intent(out) :: iso_ids(:)  ! holds chem_ids for input and output species
     271              :          character (len=*), intent(out) :: op  ! e.g., 'pg', 'wk', 'to', or ...
     272              :          integer, intent(out) :: ierr
     273              : 
     274              :          integer :: len, i, j, cnt, cid, extra_in, extra_out
     275              :          logical :: doing_inputs
     276              : 
     277            0 :          num_in = 0; num_out = 0; op = ''
     278            0 :          ierr = -1
     279            0 :          len = len_trim(handle)
     280            0 :          if (handle(1:2) /= 'r_') return
     281            0 :          i = 3
     282            0 :          cnt = 0
     283            0 :          doing_inputs = .true.
     284            0 :          do while (i <= len)
     285            0 :             call nxt  ! set j to last char of token
     286            0 :             cid = chem_get_iso_id(handle(i:j))
     287            0 :             if (cid == nuclide_not_found) then
     288            0 :                if (doing_inputs) then
     289            0 :                   op = handle(i:j)
     290            0 :                   extra_in = -1
     291            0 :                   extra_out = -1
     292            0 :                   if (j == i+1) then  ! check 2 character ops
     293            0 :                      select case (op(1:1))
     294              :                         case ('p')
     295            0 :                            extra_in = ih1
     296              :                         case ('a')
     297            0 :                            extra_in = ihe4
     298              :                         case ('n')
     299            0 :                            extra_in = ineut
     300              :                         case ('g')
     301            0 :                            extra_in = 0
     302              :                         case default
     303              :                      end select
     304            0 :                      if (extra_in >= 0) then
     305            0 :                         if (extra_in > 0) then
     306            0 :                            cnt = cnt+1
     307            0 :                            if (cnt /= 2) then
     308              :                               !write(*,*) 'failed to parse ' // &
     309              :                               !   trim(handle) // ' -- problem with ' // handle(i:j)
     310              :                               return
     311              :                            end if
     312            0 :                            if (chem_isos% Z(iso_ids(1)) >= chem_isos% Z(extra_in)) then
     313            0 :                               iso_ids(2) = iso_ids(1)
     314            0 :                               iso_ids(1) = extra_in
     315              :                            else
     316            0 :                               iso_ids(2) = extra_in
     317              :                            end if
     318              :                         end if
     319            0 :                         select case (op(2:2))
     320              :                            case ('p')
     321            0 :                               extra_out = ih1
     322              :                            case ('a')
     323            0 :                               extra_out = ihe4
     324              :                            case ('n')
     325            0 :                               extra_out = ineut
     326              :                            case ('g')
     327              :                               extra_out = 0
     328              :                            case default
     329              :                               !write(*,*) 'failed to parse ' // &
     330              :                               !   trim(handle) // ' -- problem with ' // handle(i:j)
     331            0 :                               return
     332              :                         end select
     333              :                      end if
     334              :                   end if
     335            0 :                   num_in = cnt
     336            0 :                   doing_inputs = .false.
     337            0 :                   if (extra_out > 0) then
     338            0 :                      cnt = cnt+1
     339            0 :                      iso_ids(cnt) = extra_out
     340              :                   end if
     341              :                else
     342              :                   !write(*,*) 'failed to parse ' // &
     343              :                   !   trim(handle) // ' -- problem with ' // handle(i:j)
     344              :                   return
     345              :                end if
     346              :             else
     347            0 :                cnt = cnt+1
     348            0 :                iso_ids(cnt) = cid
     349              :             end if
     350            0 :             i = j+2
     351              :          end do
     352            0 :          num_out = cnt - num_in
     353            0 :          ierr = 0
     354              : 
     355              :          contains
     356              : 
     357            0 :          subroutine nxt
     358            0 :             j = i
     359              :             do
     360            0 :                if (j >= len) return
     361            0 :                j = j+1
     362            0 :                if (handle(j:j) == '_') then
     363            0 :                   j = j-1; return
     364              :                end if
     365              :             end do
     366              :          end subroutine nxt
     367              : 
     368              : 
     369              :       end subroutine do_parse_reaction_handle
     370              : 
     371       231121 :       subroutine reaction_handle(num_in, num_out, iso_ids, reaction_flag, handle)
     372              :          use chem_def, only: chem_isos
     373              :          integer, intent(in) :: num_in, num_out
     374              :          integer, intent(in) :: iso_ids(:)
     375              :          character (len=*), intent(in) :: reaction_flag
     376              :          character (len=*), intent(out) :: handle
     377              :          logical, parameter :: reverse = .false.
     378       231121 :          call get1_reaction_handle(num_in, num_out, iso_ids, chem_isos, reverse, reaction_flag, handle)
     379       231121 :       end subroutine reaction_handle
     380              : 
     381            0 :       subroutine reverse_reaction_handle(num_in, num_out, iso_ids, handle)
     382              :          use chem_def, only: chem_isos
     383              :          integer, intent(in) :: num_in, num_out
     384              :          integer, intent(in) :: iso_ids(:)
     385              :          character (len=*), intent(out) :: handle
     386              :          logical, parameter :: reverse = .true.
     387              :          character (len=1), parameter :: reaction_flag = '-'
     388            0 :          call get1_reaction_handle(num_in, num_out, iso_ids, chem_isos, reverse, reaction_flag, handle)
     389            0 :       end subroutine reverse_reaction_handle
     390              : 
     391       145554 :       subroutine get_reaction_handle(num_in, num_out, pspecies, nuclides, reaction_flag, handle)
     392              :          integer, intent(in) :: num_in, num_out
     393              :          integer, intent(in) :: pspecies(:)
     394              :          type(nuclide_data), intent(in) :: nuclides
     395              :          character (len=*), intent(in) :: reaction_flag
     396              :          character (len=*), intent(out) :: handle
     397              :          logical, parameter :: reverse = .false.
     398       145554 :          call get1_reaction_handle(num_in, num_out, pspecies, nuclides, reverse, reaction_flag, handle)
     399       145554 :       end subroutine get_reaction_handle
     400              : 
     401       100290 :       subroutine get_reverse_reaction_handle(num_in, num_out, pspecies, nuclides, handle)
     402              :          integer, intent(in) :: num_in, num_out
     403              :          integer, intent(in) :: pspecies(:)
     404              :          type(nuclide_data), intent(in) :: nuclides
     405              :          character (len=*), intent(out) :: handle
     406              :          logical, parameter :: reverse = .true.
     407              :          character (len=1), parameter :: reaction_flag = '-'
     408       100290 :          call get1_reaction_handle(num_in, num_out, pspecies, nuclides, reverse, reaction_flag, handle)
     409       100290 :       end subroutine get_reverse_reaction_handle
     410              : 
     411       476965 :       subroutine get1_reaction_handle( &
     412       476965 :             num_in, num_out, pspecies_in, nuclides, reverse, reaction_flag, handle)
     413              :          use chem_def, only: ih1, ih2, ih3, ihe3, ihe4, ibe7, ili7, chem_isos
     414              :          integer, intent(in) :: num_in, num_out
     415              :          integer, intent(in) :: pspecies_in(:)
     416              :          type(nuclide_data), intent(in) :: nuclides
     417              :          logical, intent(in) :: reverse
     418              :          character (len=*), intent(in) :: reaction_flag
     419              :          character (len=*), intent(out) :: handle
     420              : 
     421       476965 :          integer :: in1, in2, out1, out2, num, pspecies(num_in + num_out)
     422              :          logical :: do_long_form, ec_flag, wk_flag
     423              : 
     424              :          include 'formats'
     425              : 
     426       476965 :          num = num_in + num_out
     427      2167796 :          pspecies(1:num) = pspecies_in(1:num)
     428       476965 :          call sort(num_in, pspecies(1:num_in))
     429       476965 :          call sort(num_out, pspecies(num_in+1:num))
     430       476965 :          ec_flag = (reaction_flag == 'e')
     431       476965 :          wk_flag = (reaction_flag == 'w')
     432              : 
     433       476965 :          if (ec_flag) then  ! special cases
     434            7 :             if (reverse) then
     435            0 :                handle = ''
     436            0 :                return
     437              :             end if
     438            7 :             if (num_in == 2 .and. num_out == 1) then
     439              :                if (nuclides% chem_id(pspecies(1)) == ih1 .and. &
     440            3 :                    nuclides% chem_id(pspecies(2)) == ih1 .and. &
     441              :                    nuclides% chem_id(pspecies(3)) == ih2) then
     442            3 :                   handle = 'r_h1_h1_ec_h2'
     443            3 :                   return
     444              :                end if
     445            4 :             else if (num_in == 1 .and. num_out == 1) then
     446            4 :                if (nuclides% chem_id(pspecies(1)) == ihe3 .and. &
     447              :                    nuclides% chem_id(pspecies(2)) == ih3) then
     448            3 :                   handle = 'r_he3_ec_h3'
     449            3 :                   return
     450              :                end if
     451            1 :                if (nuclides% chem_id(pspecies(1)) == ibe7 .and. &
     452              :                    nuclides% chem_id(pspecies(2)) == ili7) then
     453            1 :                   handle = 'r_be7_wk_li7'
     454            1 :                   return
     455              :                end if
     456              :             end if
     457       476958 :          else if (wk_flag) then
     458        43863 :             if (reverse) then
     459            0 :                handle = ''
     460            0 :                return
     461              :             end if
     462        43863 :             if (num_in == 2 .and. num_out == 1) then
     463              :                if (nuclides% chem_id(pspecies(1)) == ih1 .and. &
     464            6 :                    nuclides% chem_id(pspecies(2)) == ih1 .and. &
     465              :                    nuclides% chem_id(pspecies(3)) == ih2) then
     466            3 :                   handle = 'r_h1_h1_wk_h2'
     467            3 :                   return
     468              :                end if
     469        43857 :             else if (num_in == 2 .and. num_out == 1) then
     470              :                if (nuclides% chem_id(pspecies(1)) == ih1 .and. &
     471            0 :                    nuclides% chem_id(pspecies(2)) == ihe3 .and. &
     472              :                    nuclides% chem_id(pspecies(3)) == ihe4) then
     473            0 :                   handle = 'r_h1_he3_wk_he4'
     474            0 :                   return
     475              :                end if
     476              :             end if
     477              :          end if
     478              : 
     479       476955 :          in1 = 0; in2 = 0; out1 = 0; out2 = 0
     480       476955 :          do_long_form = .true.
     481       476955 :          if (num_in == 1 .and. num_out == 1) then
     482        22169 :             call do_n_to_m(1,1)
     483        22169 :             do_long_form = one_one()
     484       454786 :          else if (num_in == 1 .and. num_out == 2) then
     485        23679 :             call do_n_to_m(1,2)
     486        23679 :             if (reverse) then
     487         7356 :                do_long_form = two_one()
     488              :             else
     489        16323 :                do_long_form = one_two()
     490              :             end if
     491       431107 :          else if (num_in == 2 .and. num_out == 1) then
     492       185619 :             call do_n_to_m(2,1)
     493       185619 :             if (reverse) then
     494        47556 :                do_long_form = one_two()
     495              :             else
     496       138063 :                do_long_form = two_one()
     497              :             end if
     498       245488 :          else if (num_in == 2 .and. num_out == 2) then
     499       191111 :             call do_n_to_m(2,2)
     500       191111 :             do_long_form = two_two()
     501              :          end if
     502              : 
     503       422578 :          if (do_long_form) then
     504       103360 :             call long_form
     505       373595 :          else if (out2 /= 0) then
     506       216026 :             handle = trim(handle) // '_' // nuclides% name(out2)
     507              :          else
     508       157569 :             handle = trim(handle) // '_' // nuclides% name(out1)
     509              :          end if
     510              : 
     511              : 
     512              :          contains
     513              : 
     514       953930 :          subroutine sort(n, species)
     515              :             integer :: n
     516              :             integer :: species(n)
     517              :             integer :: i, j, Zi, Ni, Zj, Nj, isomer_j, isomer_i, cid
     518              :             include 'formats'
     519      1690831 :             do i=1,n-1
     520       736901 :                cid = species(i)
     521       736901 :                if (cid <= 0) cycle
     522       736901 :                Zi = chem_isos% Z(cid)
     523       736901 :                Ni = chem_isos% N(cid)
     524       736901 :                isomer_i = chem_isos% isomeric_state(cid)
     525      2514951 :                do j=i+1,n
     526       824120 :                   cid = species(j)
     527       824120 :                   if (cid <= 0) cycle
     528       824120 :                   Zj = chem_isos% Z(cid)
     529       824120 :                   Nj = chem_isos% N(cid)
     530       824120 :                   isomer_j = chem_isos% isomeric_state(cid)
     531       824120 :                   if (Zj > Zi) cycle
     532       147600 :                   if (Zj == Zi) then
     533       147570 :                      if (Nj > Ni) cycle
     534       147516 :                      if (Nj == Ni) then
     535       147498 :                         if (isomer_j >= isomer_i) cycle
     536              :                      end if
     537              :                   end if
     538              :                   ! exchange i and j
     539           48 :                   species(j) = species(i)
     540           48 :                   species(i) = cid
     541           48 :                   Zi = Zj
     542           48 :                   Ni = Nj
     543      1561021 :                   isomer_i = isomer_j
     544              :                end do
     545              :             end do
     546       953930 :          end subroutine sort
     547              : 
     548       103360 :          subroutine long_form
     549              :             integer :: i, cid
     550              :             character (len=3) :: op
     551       103360 :             handle = 'r_'
     552       103360 :             if (wk_flag) then
     553        22719 :                op = 'wk_'
     554        80641 :             else if (ec_flag) then
     555            0 :                op = 'ec_'
     556              :             else
     557        80641 :                op = 'to_'
     558              :             end if
     559       103360 :             if (reverse) then
     560          753 :                do i = num_in+1,num_in+num_out
     561          525 :                   cid = pspecies(i)
     562          753 :                   handle = trim(handle) // trim(nuclides% name(cid)) // '_'
     563              :                end do
     564          228 :                handle = trim(handle) // op
     565          717 :                do i = 1,num_in
     566          489 :                   cid = pspecies(i)
     567          489 :                   handle = trim(handle) // trim(nuclides% name(cid))
     568          717 :                   if (i < num_in) handle = trim(handle) // '_'
     569              :                end do
     570              :             else
     571       306733 :                do i = 1,num_in
     572       203601 :                   cid = pspecies(i)
     573       306733 :                   handle = trim(handle) // trim(nuclides% name(cid)) // '_'
     574              :                end do
     575       103132 :                handle = trim(handle) // op
     576       329952 :                do i = num_in+1,num_in+num_out
     577       226820 :                   cid = pspecies(i)
     578       226820 :                   handle = trim(handle) // trim(nuclides% name(cid))
     579       329952 :                   if (i < num_in+num_out) handle = trim(handle) // '_'
     580              :                end do
     581              :             end if
     582       103360 :          end subroutine long_form
     583              : 
     584        22169 :          logical function one_one()
     585        22169 :             one_one = .true.
     586        22169 :             if (in1 == 0 .or. out1 == 0) return
     587        22169 :             one_one = .false.
     588        22169 :             if (nuclides% Z(out1) == nuclides% Z(in1) - 1 .and. &
     589              :                 nuclides% N(out1) == nuclides% N(in1) + 1) then
     590         6425 :                handle = trim(handle) // '_wk'
     591        15744 :             else if (nuclides% Z(out1) == nuclides% Z(in1) + 1 .and. &
     592              :                      nuclides% N(out1) == nuclides% N(in1) - 1) then
     593        15744 :                handle = trim(handle) // '_wk-minus'
     594              :             else
     595              :                one_one = .true.
     596              :             end if
     597              :          end function one_one
     598              : 
     599        63879 :          logical function one_two()
     600        63879 :             one_two = .true.
     601        63879 :             if (in1 == 0 .or. out1 == 0 .or. out2 == 0 .or. out1 == out2) return
     602        63870 :             one_two = .false.
     603              :             if (nuclides% Z(out1) == 0 .and. nuclides% N(out1) == 1 .and. &
     604        63870 :                      nuclides% Z(out2) == nuclides% Z(in1) .and. &
     605              :                      nuclides% N(out2) == nuclides% N(in1) - 1) then
     606        22065 :                handle = trim(handle) // '_gn'
     607              :             else if (nuclides% Z(out1) == 1 .and. nuclides% N(out1) == 0 .and. &
     608        41805 :                      nuclides% Z(out2) == nuclides% Z(in1) - 1 .and. &
     609              :                      nuclides% N(out2) == nuclides% N(in1)) then
     610        15759 :                handle = trim(handle) // '_gp'
     611              :             else if (nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     612        26046 :                      nuclides% Z(out2) == nuclides% Z(in1) - 2 .and. &
     613              :                      nuclides% N(out2) == nuclides% N(in1) - 2) then
     614        17082 :                handle = trim(handle) // '_ga'
     615              :             else if (nuclides% Z(out1) == 1 .and. nuclides% N(out1) == 0 .and. &
     616         8964 :                      nuclides% Z(out2) == nuclides% Z(in1) - 2 .and. &
     617              :                      nuclides% N(out2) == nuclides% N(in1) + 1) then
     618          324 :                handle = trim(handle) // '_wk_h1'
     619              :             else if (nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     620         8640 :                      nuclides% Z(out2) == nuclides% Z(in1) - 3 .and. &
     621              :                      nuclides% N(out2) == nuclides% N(in1) - 1) then
     622           42 :                handle = trim(handle) // '_wk_he4'
     623              :             else
     624              :                one_two = .true.
     625              :             end if
     626              :          end function one_two
     627              : 
     628       145419 :          logical function two_one()
     629              :             include 'formats'
     630       145419 :             two_one = .true.
     631       145419 :             if (in1 == 0 .or. in2 == 0 .or. out1 == 0 .or. in1 == in2) return
     632       135406 :             two_one = .false.
     633              :             if (nuclides% Z(in1) == 0 .and. nuclides% N(in1) == 1 .and. &
     634       135406 :                      nuclides% Z(out1) == nuclides% Z(in2) .and. &
     635              :                      nuclides% N(out1) == nuclides% N(in2) + 1) then
     636        22146 :                handle = trim(handle) // '_ng'
     637              :             else if (nuclides% Z(in1) == 1 .and. nuclides% N(in1) == 0 .and. &
     638       113260 :                      nuclides% Z(out1) == nuclides% Z(in2) + 1 .and. &
     639              :                      nuclides% N(out1) == nuclides% N(in2)) then
     640        66115 :                handle = trim(handle) // '_pg'
     641              :             else if (nuclides% Z(in1) == 2 .and. nuclides% N(in1) == 2 .and. &
     642        47145 :                      nuclides% Z(out1) == nuclides% Z(in2) + 2 .and. &
     643              :                      nuclides% N(out1) == nuclides% N(in2) + 2) then
     644        47139 :                handle = trim(handle) // '_ag'
     645              :             else
     646              :                two_one = .true.
     647              :             end if
     648              :          end function two_one
     649              : 
     650       191111 :          logical function two_two()
     651       191111 :             two_two = .true.
     652              : 
     653       191111 :             if (in1 == 0 .or. in2 == 0 .or. out1 == 0 .or. out2 == 0) return
     654              : 
     655              :             ! Special case r_li7_pa_he4, this must come first otherwise the out1==out2
     656              :             ! check will label this rate as a _to_ reaction instead of an _ap reaction
     657              :             if (nuclides% Z(in1) == 1 .and. nuclides% N(in1) == 0 .and. &
     658              :                nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     659              :                nuclides% Z(out2) == 2 .and.  nuclides% N(out2) == 2 .and. &
     660       191111 :                nuclides% Z(in2) == 3 .and. nuclides% N(in2) == 4) then
     661           12 :                handle = trim(handle) // '_pa'
     662           12 :                two_two = .false.
     663           12 :                return
     664              :             end if
     665              : 
     666       191099 :             if(in1==in2 .or. out1==out2) return
     667              : 
     668       170932 :             two_two = .false.
     669              :             if (nuclides% Z(in1) == 2 .and. nuclides% N(in1) == 2 .and. &
     670              :                      nuclides% Z(out1) == 1 .and. nuclides% N(out1) == 0 .and. &
     671       170932 :                      nuclides% Z(out2) == nuclides% Z(in2) + 1 .and. &
     672              :                      nuclides% N(out2) == nuclides% N(in2) + 2) then
     673        25349 :                handle = trim(handle) // '_ap'
     674              :             else if (nuclides% Z(in1) == 1 .and. nuclides% N(in1) == 0 .and. &
     675              :                      nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     676       145583 :                      nuclides% Z(out2) == nuclides% Z(in2) - 1 .and. &
     677              :                      nuclides% N(out2) == nuclides% N(in2) - 2) then
     678        75435 :                 handle = trim(handle) // '_pa'
     679              :             else if (nuclides% Z(in1) == 2 .and. nuclides% N(in1) == 2 .and. &
     680              :                      nuclides% Z(out1) == 0 .and. nuclides% N(out1) == 1 .and. &
     681        70148 :                      nuclides% Z(out2) == nuclides% Z(in2) + 2 .and. &
     682              :                      nuclides% N(out2) == nuclides% N(in2) + 1) then
     683        14997 :                 handle = trim(handle) // '_an'
     684              :             else if (nuclides% Z(in1) == 0 .and. nuclides% N(in1) == 1 .and. &
     685              :                      nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     686        55151 :                      nuclides% Z(out2) == nuclides% Z(in2) - 2 .and. &
     687              :                      nuclides% N(out2) == nuclides% N(in2) - 1) then
     688        15033 :                 handle = trim(handle) // '_na'
     689              :             else if (nuclides% Z(in1) == 1 .and. nuclides% N(in1) == 0 .and. &
     690              :                      nuclides% Z(out1) == 0 .and. nuclides% N(out1) == 1 .and. &
     691        40118 :                      nuclides% Z(out2) == nuclides% Z(in2) + 1 .and. &
     692              :                      nuclides% N(out2) == nuclides% N(in2) - 1) then
     693        14964 :                 handle = trim(handle) // '_pn'
     694              :             else if (nuclides% Z(in1) == 0 .and. nuclides% N(in1) == 1 .and. &
     695              :                      nuclides% Z(out1) == 1 .and. nuclides% N(out1) == 0 .and. &
     696        25154 :                      nuclides% Z(out2) == nuclides% Z(in2) - 1 .and. &
     697              :                      nuclides% N(out2) == nuclides% N(in2) + 1) then
     698        14964 :                 handle = trim(handle) // '_np'
     699              :             else
     700              :                two_two = .true.
     701              :             end if
     702              :          end function two_two
     703              : 
     704       422578 :          subroutine do_n_to_m(n,m)
     705              :             integer, intent(in) :: n, m  ! each is either 1 or 2
     706       422578 :             in1 = 0; in2 = 0; out1 = 0; out2 = 0
     707       422578 :             if (.not. reverse) then
     708       322399 :                in1 = pspecies(1)
     709       322399 :                if (n == 2) then
     710       283907 :                   in2 = pspecies(2)
     711       283907 :                   if (in2 == 0) then
     712            0 :                      in1 = 0; return
     713              :                   end if
     714       283907 :                   call switch_if_necessary(in1,in2)
     715       283907 :                   handle = 'r_' // nuclides% name(in2)
     716        38492 :                else if (n == 1) then
     717        38492 :                   handle = 'r_' // nuclides% name(in1)
     718              :                else
     719            0 :                   in1 = 0
     720            0 :                   return
     721              :                end if
     722       322399 :                out1 = pspecies(n+1)
     723       322399 :                if (m == 2) then
     724       162167 :                   out2 = pspecies(n+2)
     725       162167 :                   call switch_if_necessary(out1,out2)
     726              :                end if
     727              :             else
     728       100179 :                in1 = pspecies(n+1)
     729       100179 :                if (m == 2) then
     730        52623 :                   in2 = pspecies(n+2)
     731        52623 :                   if (in2 == 0) then
     732            0 :                      in1 = 0; return
     733              :                   end if
     734        52623 :                   call switch_if_necessary(in1,in2)
     735        52623 :                   handle = 'r_' // nuclides% name(in2)
     736        47556 :                else if (m == 1) then
     737        47556 :                   handle = 'r_' // nuclides% name(in1)
     738              :                else
     739            0 :                   in1 = 0
     740            0 :                   return
     741              :                end if
     742       100179 :                out1 = pspecies(1)
     743       100179 :                if (n == 2) then
     744        92823 :                   out2 = pspecies(2)
     745        92823 :                   call switch_if_necessary(out1,out2)
     746              :                end if
     747              :             end if
     748              :          end subroutine do_n_to_m
     749              : 
     750       591520 :          subroutine switch_if_necessary(iso1,iso2)
     751              :             integer, intent(inout) :: iso1, iso2
     752              :             integer :: j
     753       591520 :             if (nuclides% Z(iso2) == 1 .and. nuclides% N(iso2) == 0) then  ! iso2 is ih1
     754           18 :                j = iso1; iso1 = iso2; iso2 = j; return
     755              :             end if
     756       591502 :             if (nuclides% Z(iso2) == 2 .and. nuclides% N(iso2) == 2) then  ! iso2 is ihe4
     757        10124 :                if (nuclides% Z(iso1) == 1 .and. nuclides% N(iso1) == 0) return  ! iso1 is ih1
     758          102 :                j = iso1; iso1 = iso2; iso2 = j; return
     759              :             end if
     760              :          end subroutine switch_if_necessary
     761              : 
     762              : 
     763              :       end subroutine get1_reaction_handle
     764              : 
     765              : 
     766              :       end module reaclib_support
        

Generated by: LCOV version 2.0-1