LCOV - code coverage report
Current view: top level - rates/private - reaclib_support.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.1 % 376 305
Test Date: 2025-05-08 18:23:42 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            5 :       subroutine set_up_network_information(rates)
      31              :          type(reaction_data), intent(inout) :: rates
      32              :          integer :: current_chapter, i
      33              : 
      34              :          ! set up bookmarks
      35            5 :          current_chapter = 0
      36            5 :          rates% nchapters_included = 0
      37           60 :          rates% chapters_present = 0
      38          170 :          rates% bookmarks = 0
      39       242595 :          do i = 1, rates% nreactions
      40       242595 :             new_chapter : if (rates% chapter(i) /= current_chapter) then
      41              :                ! close out the chapter we just left.
      42           55 :                if (current_chapter /= 0) rates% bookmarks(2,current_chapter) = i-1
      43              :                ! set up information on the new chapter
      44           55 :                current_chapter = rates% chapter(i)
      45           55 :                rates% nchapters_included = rates% nchapters_included + 1
      46           55 :                rates% chapters_present(rates% nchapters_included) = current_chapter
      47           55 :                rates% bookmarks(1,current_chapter) = i
      48              :             end if new_chapter
      49              :          end do
      50              :          ! mark the end of the last chapter
      51            5 :          rates% bookmarks(2,current_chapter) = rates% nreactions
      52            5 :       end subroutine set_up_network_information
      53              : 
      54              : 
      55            5 :       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            5 :          if (.not.associated(rates% weight)) then
      63              :             return
      64              :          end if
      65              : 
      66       242595 :          do i = 1, rates% nreactions
      67       242590 :             i1 = -1; i2 = -2; i3 = -3; i4 = -4
      68       321865 :             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        79275 :                   i1 = rates% pspecies(1,i)
      74        79275 :                   i2 = rates% pspecies(2,i)
      75              :                case (r_two_two)
      76        75445 :                   i1 = rates% pspecies(1,i)
      77        75445 :                   i2 = rates% pspecies(2,i)
      78              :                case (r_two_three)
      79          115 :                   i1 = rates% pspecies(1,i)
      80          115 :                   i2 = rates% pspecies(2,i)
      81              :                case (r_two_four)
      82           20 :                   i1 = rates% pspecies(1,i)
      83           20 :                   i2 = rates% pspecies(2,i)
      84              :                case (r_three_one)
      85           35 :                   i1 = rates% pspecies(1,i)
      86           35 :                   i2 = rates% pspecies(2,i)
      87           35 :                   i3 = rates% pspecies(3,i)
      88              :                case (r_three_two)
      89            5 :                   i1 = rates% pspecies(1,i)
      90            5 :                   i2 = rates% pspecies(2,i)
      91            5 :                   i3 = rates% pspecies(3,i)
      92              :                case (r_four_two)
      93           10 :                   i1 = rates% pspecies(1,i)
      94           10 :                   i2 = rates% pspecies(2,i)
      95           10 :                   i3 = rates% pspecies(3,i)
      96       242590 :                   i4 = rates% pspecies(4,i)
      97              :                case (r_one_four)
      98              :             end select
      99       242595 :             call set_weight(rates% weight(i))
     100              :          end do
     101              : 
     102       242595 :          do i = 1, rates% nreactions
     103       242590 :             i1 = -1; i2 = -2; i3 = -3; i4 = -4
     104       269795 :             select case (rates% chapter(i))
     105              :                case (r_one_one)
     106              :                case (r_one_two)
     107        27205 :                   i1 = rates% pspecies(2,i)
     108        27205 :                   i2 = rates% pspecies(3,i)
     109              :                case (r_one_three)
     110        12900 :                   i1 = rates% pspecies(2,i)
     111        12900 :                   i2 = rates% pspecies(3,i)
     112        12900 :                   i3 = rates% pspecies(4,i)
     113              :                case (r_two_one)
     114              :                case (r_two_two)
     115        75445 :                   i1 = rates% pspecies(3,i)
     116        75445 :                   i2 = rates% pspecies(4,i)
     117              :                case (r_two_three)
     118          115 :                   i1 = rates% pspecies(3,i)
     119          115 :                   i2 = rates% pspecies(4,i)
     120          115 :                   i3 = rates% pspecies(5,i)
     121              :                case (r_two_four)
     122           20 :                   i1 = rates% pspecies(3,i)
     123           20 :                   i2 = rates% pspecies(4,i)
     124           20 :                   i3 = rates% pspecies(5,i)
     125           20 :                   i4 = rates% pspecies(6,i)
     126              :                case (r_three_one)
     127              :                case (r_three_two)
     128            5 :                   i1 = rates% pspecies(4,i)
     129            5 :                   i2 = rates% pspecies(5,i)
     130              :                case (r_four_two)
     131           10 :                   i1 = rates% pspecies(5,i)
     132           10 :                   i2 = rates% pspecies(6,i)
     133              :                case (r_one_four)
     134        10625 :                   i1 = rates% pspecies(2,i)
     135        10625 :                   i2 = rates% pspecies(3,i)
     136        10625 :                   i3 = rates% pspecies(4,i)
     137       242590 :                   i4 = rates% pspecies(5,i)
     138              :             end select
     139              : 
     140       242595 :             call set_weight(rates% weight_reverse(i))
     141              : 
     142              :          end do
     143              : 
     144              : 
     145              :          contains
     146              : 
     147              : 
     148       485180 :          subroutine set_weight(w)
     149              :             ! nuclei are sorted, so if identical, then are adjacent in list
     150              :             real(dp), intent(out) :: w
     151       485180 :             if (i1 == i2 .and. i2 == i3 .and. i3 == i4) then
     152            0 :                w = 1d0/24d0
     153       485180 :             else if (i2 == i3 .and. (i1 == i2 .or. i3 == i4)) then
     154        10665 :                w = 1d0/6d0
     155       474515 :             else if (i1 == i2) then
     156        13050 :                if (i3 == i4) then
     157           10 :                   w = 1d0/4d0
     158              :                else
     159        13040 :                   w = 1d0/2d0
     160              :                end if
     161       461465 :             else if (i2 == i3 .or. i3 == i4) then
     162           90 :                w = 1d0/2d0
     163              :             else
     164       461375 :                w = 1d0
     165              :             end if
     166       485180 :          end subroutine set_weight
     167              : 
     168              : 
     169              :       end subroutine assign_weights
     170              : 
     171              : 
     172            5 :       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            5 :          real(dp) :: mp, mn
     178           35 :          real(dp),  dimension(max_species_per_reaction) :: g   ! statistical weights of nuclides
     179           35 :          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            5 :          real(dp) :: fac, massfac, sum1, sum2, tmp
     183              : 
     184              : 
     185              :          include 'formats'
     186              : 
     187              :          ! Get these consistently from the isotopes.data file
     188            5 :          mp=winvn%W(chem_get_iso_id('prot'))
     189            5 :          mn=winvn%W(chem_get_iso_id('neut'))
     190              : 
     191            5 :          fac = pow(1d9*kB/(2d0*pi*hbar*hbar*NA),1.5d0)/NA
     192            5 :          massfac = conv*NA/(c*c)
     193              : 
     194       242595 :          rates% weak_mask = 1d0
     195       242595 :          loop_over_rates: do i = 1,rates% nreactions
     196              :             ! weak rates don't have inverses, so set to innocuous values and mask out
     197       242590 :             if (rates% reaction_flag(i) == 'w' .or. rates% reaction_flag(i) == 'e') then
     198        75440 :                rates% weak_mask(i) = 0d0
     199       226320 :                rates% inverse_coefficients(:,i) = [-huge(1d0), 0d0]
     200        75440 :                rates% inverse_exp(i) = 0d0
     201      1886000 :                rates% inverse_part(:,i) = 1d0
     202              :                cycle loop_over_rates
     203              :             end if
     204       167150 :             Ni = Nin(rates% chapter(i))
     205       167150 :             No = Nout(rates% chapter(i))
     206       167150 :             Nt = Ni+No
     207       744410 :             ps(1:Nt) = rates% pspecies(1:Nt,i)
     208       744410 :             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       744410 :             mass(1:Nt) = winvn% W(ps(1:Nt))
     211              : 
     212              :             ! log(prefactor of reverse_ratio)
     213       744410 :             tmp = product(mass(1:Ni))/product(mass(Ni+1:Nt))
     214       911560 :             rates% inverse_coefficients(1,i) = pow(tmp,1.5d0*(Ni-No))*(product(g(1:Ni))/product(g(Ni+1:Nt)))
     215              : 
     216              :             ! -Q/(kB*10**9)
     217       489250 :             sum1 = sum(winvn% binding_energy(ps(1:Ni)))
     218       422310 :             sum2 = sum(winvn% binding_energy(ps(Ni+1:Nt)))
     219       167150 :             rates% inverse_coefficients(2,i) = (sum1-sum2)*conv/kB/1d9
     220              : 
     221              :             ! see equation 21 in Reichert et al. 2023 (https://doi.org/10.3847/1538-4365/acf033)
     222              :             ! delta_reactants/delta_products is handled in net.
     223              :             ! fac == (mu * kb * T / (2 * pi * hbar^2))^3/2 term with out a T^3/2.
     224              :             ! fac shows up as fac^(Ni-No) in rates% inverse_coefficients(1,i)
     225              :             ! so rates% inverse_coefficients(1,i)  contains terms for
     226              :             ! fac^(n) == fac^(Ni-No), where n = Ni - No.
     227              : 
     228              :             ! The T makes its way back into our expression inside
     229              :             ! the subroutine compute_some_inverse_lambdas, in reaclib_eval.f90.
     230              :             ! It appears in log form as 1.5d0*rates% inverse_exp(i)*lnT9, where,
     231              :             ! rates% inverse_exp(i) = Ni-No, so,
     232              :             ! 1.5d0*rates% inverse_exp(i)*lnT9 == ln(T^(3n/2)), where n = Ni-No.
     233       167150 :             rates% inverse_exp(i) = Ni - No  ! We use this term in a log() expression in reaclib_eval
     234              : 
     235              :             ! Ni-No should be 0 for non-photo-disintegration reverse rates
     236              :             ! and >=1 for photos's in the reverse channel
     237       167150 :             if (Ni-No /= 0) then
     238              :                ! whether endothermic or exothermic,
     239              :                ! Ni-No handles the sign of Q from rates% inverse_coefficients(2,i)
     240        91705 :                rates% inverse_coefficients(1,i) = rates% inverse_coefficients(1,i) * pow(fac, Ni-No)
     241              :                ! negative values of Q denote endothermic photodisintegrations
     242              :                ! We multiply by fac^|Ni-No| as we want to compute
     243              :                ! rate_photo/rate_forward
     244              : 
     245              :                ! positive values of Q denote exothermic photodisintegrations
     246              :                ! We DIVIDE by fac^|Ni-No| as we want to compute
     247              :                ! rate_reverse/rate_photo
     248              :             else  ! Ni - No = 0
     249        75445 :                rates% inverse_exp(i) = 0  ! ensure this is 0.
     250              :                rates% inverse_coefficients(1,i) = rates% inverse_coefficients(1,i)  ! no point calling pow(fac,0)
     251              :             end if
     252       167150 :             rates% inverse_coefficients(1,i) = log(rates% inverse_coefficients(1,i))
     253              : 
     254              : 
     255              :             rates% inverse_part(:,i) = product(winvn% pfcn(1:npart,ps(1:Ni)),dim=2)/ &
     256     18032995 :                & product(winvn% pfcn(1:npart,ps(Ni+1:Nt)),dim=2)
     257              :          end   do loop_over_rates
     258            5 :       end subroutine compute_rev_ratio
     259              : 
     260            0 :       subroutine do_parse_reaction_handle(handle, num_in, num_out, iso_ids, op, ierr)
     261              :          use chem_def
     262              :          use chem_lib
     263              :          character (len=*), intent(in) :: handle
     264              :          integer, intent(out) :: num_in, num_out
     265              :          integer, intent(out) :: iso_ids(:)  ! holds chem_ids for input and output species
     266              :          character (len=*), intent(out) :: op  ! e.g., 'pg', 'wk', 'to', or ...
     267              :          integer, intent(out) :: ierr
     268              : 
     269              :          integer :: len, i, j, cnt, cid, extra_in, extra_out
     270              :          logical :: doing_inputs
     271              : 
     272            0 :          num_in = 0; num_out = 0; op = ''
     273            0 :          ierr = -1
     274            0 :          len = len_trim(handle)
     275            0 :          if (handle(1:2) /= 'r_') return
     276            0 :          i = 3
     277            0 :          cnt = 0
     278            0 :          doing_inputs = .true.
     279            0 :          do while (i <= len)
     280            0 :             call nxt  ! set j to last char of token
     281            0 :             cid = chem_get_iso_id(handle(i:j))
     282            0 :             if (cid == nuclide_not_found) then
     283            0 :                if (doing_inputs) then
     284            0 :                   op = handle(i:j)
     285            0 :                   extra_in = -1
     286            0 :                   extra_out = -1
     287            0 :                   if (j == i+1) then  ! check 2 character ops
     288            0 :                      select case (op(1:1))
     289              :                         case ('p')
     290            0 :                            extra_in = ih1
     291              :                         case ('a')
     292            0 :                            extra_in = ihe4
     293              :                         case ('n')
     294            0 :                            extra_in = ineut
     295              :                         case ('g')
     296            0 :                            extra_in = 0
     297              :                         case default
     298              :                      end select
     299            0 :                      if (extra_in >= 0) then
     300            0 :                         if (extra_in > 0) then
     301            0 :                            cnt = cnt+1
     302            0 :                            if (cnt /= 2) then
     303              :                               !write(*,*) 'failed to parse ' // &
     304              :                               !   trim(handle) // ' -- problem with ' // handle(i:j)
     305              :                               return
     306              :                            end if
     307            0 :                            if (chem_isos% Z(iso_ids(1)) >= chem_isos% Z(extra_in)) then
     308            0 :                               iso_ids(2) = iso_ids(1)
     309            0 :                               iso_ids(1) = extra_in
     310              :                            else
     311            0 :                               iso_ids(2) = extra_in
     312              :                            end if
     313              :                         end if
     314            0 :                         select case (op(2:2))
     315              :                            case ('p')
     316            0 :                               extra_out = ih1
     317              :                            case ('a')
     318            0 :                               extra_out = ihe4
     319              :                            case ('n')
     320            0 :                               extra_out = ineut
     321              :                            case ('g')
     322              :                               extra_out = 0
     323              :                            case default
     324              :                               !write(*,*) 'failed to parse ' // &
     325              :                               !   trim(handle) // ' -- problem with ' // handle(i:j)
     326            0 :                               return
     327              :                         end select
     328              :                      end if
     329              :                   end if
     330            0 :                   num_in = cnt
     331            0 :                   doing_inputs = .false.
     332            0 :                   if (extra_out > 0) then
     333            0 :                      cnt = cnt+1
     334            0 :                      iso_ids(cnt) = extra_out
     335              :                   end if
     336              :                else
     337              :                   !write(*,*) 'failed to parse ' // &
     338              :                   !   trim(handle) // ' -- problem with ' // handle(i:j)
     339              :                   return
     340              :                end if
     341              :             else
     342            0 :                cnt = cnt+1
     343            0 :                iso_ids(cnt) = cid
     344              :             end if
     345            0 :             i = j+2
     346              :          end do
     347            0 :          num_out = cnt - num_in
     348            0 :          ierr = 0
     349              : 
     350              :          contains
     351              : 
     352            0 :          subroutine nxt
     353            0 :             j = i
     354              :             do
     355            0 :                if (j >= len) return
     356            0 :                j = j+1
     357            0 :                if (handle(j:j) == '_') then
     358            0 :                   j = j-1; return
     359              :                end if
     360              :             end do
     361            0 :          end subroutine nxt
     362              : 
     363              : 
     364              :       end subroutine do_parse_reaction_handle
     365              : 
     366       232219 :       subroutine reaction_handle(num_in, num_out, iso_ids, reaction_flag, handle)
     367              :          use chem_def, only: chem_isos
     368              :          integer, intent(in) :: num_in, num_out
     369              :          integer, intent(in) :: iso_ids(:)
     370              :          character (len=*), intent(in) :: reaction_flag
     371              :          character (len=*), intent(out) :: handle
     372              :          logical, parameter :: reverse = .false.
     373       232219 :          call get1_reaction_handle(num_in, num_out, iso_ids, chem_isos, reverse, reaction_flag, handle)
     374       232219 :       end subroutine reaction_handle
     375              : 
     376            0 :       subroutine reverse_reaction_handle(num_in, num_out, iso_ids, handle)
     377       232219 :          use chem_def, only: chem_isos
     378              :          integer, intent(in) :: num_in, num_out
     379              :          integer, intent(in) :: iso_ids(:)
     380              :          character (len=*), intent(out) :: handle
     381              :          logical, parameter :: reverse = .true.
     382              :          character (len=1), parameter :: reaction_flag = '-'
     383            0 :          call get1_reaction_handle(num_in, num_out, iso_ids, chem_isos, reverse, reaction_flag, handle)
     384            0 :       end subroutine reverse_reaction_handle
     385              : 
     386       242590 :       subroutine get_reaction_handle(num_in, num_out, pspecies, nuclides, reaction_flag, handle)
     387              :          integer, intent(in) :: num_in, num_out
     388              :          integer, intent(in) :: pspecies(:)
     389              :          type(nuclide_data), intent(in) :: nuclides
     390              :          character (len=*), intent(in) :: reaction_flag
     391              :          character (len=*), intent(out) :: handle
     392              :          logical, parameter :: reverse = .false.
     393       242590 :          call get1_reaction_handle(num_in, num_out, pspecies, nuclides, reverse, reaction_flag, handle)
     394            0 :       end subroutine get_reaction_handle
     395              : 
     396       167150 :       subroutine get_reverse_reaction_handle(num_in, num_out, pspecies, nuclides, handle)
     397              :          integer, intent(in) :: num_in, num_out
     398              :          integer, intent(in) :: pspecies(:)
     399              :          type(nuclide_data), intent(in) :: nuclides
     400              :          character (len=*), intent(out) :: handle
     401              :          logical, parameter :: reverse = .true.
     402              :          character (len=1), parameter :: reaction_flag = '-'
     403       167150 :          call get1_reaction_handle(num_in, num_out, pspecies, nuclides, reverse, reaction_flag, handle)
     404       167150 :       end subroutine get_reverse_reaction_handle
     405              : 
     406       641959 :       subroutine get1_reaction_handle( &
     407       641959 :             num_in, num_out, pspecies_in, nuclides, reverse, reaction_flag, handle)
     408              :          use chem_def, only: ih1, ih2, ih3, ihe3, ihe4, ibe7, ili7, chem_isos
     409              :          integer, intent(in) :: num_in, num_out
     410              :          integer, intent(in) :: pspecies_in(:)
     411              :          type(nuclide_data), intent(in) :: nuclides
     412              :          logical, intent(in) :: reverse
     413              :          character (len=*), intent(in) :: reaction_flag
     414              :          character (len=*), intent(out) :: handle
     415              : 
     416      1283918 :          integer :: in1, in2, out1, out2, num, pspecies(num_in + num_out)
     417              :          logical :: do_long_form, ec_flag, wk_flag
     418              : 
     419              :          include 'formats'
     420              : 
     421       641959 :          num = num_in + num_out
     422      2887928 :          pspecies(1:num) = pspecies_in(1:num)
     423       641959 :          call sort(num_in, pspecies(1:num_in))
     424       641959 :          call sort(num_out, pspecies(num_in+1:num))
     425       641959 :          ec_flag = (reaction_flag == 'e')
     426       641959 :          wk_flag = (reaction_flag == 'w')
     427              : 
     428       641959 :          if (ec_flag) then  ! special cases
     429           12 :             if (reverse) then
     430            0 :                handle = ''
     431            0 :                return
     432              :             end if
     433           12 :             if (num_in == 2 .and. num_out == 1) then
     434              :                if (nuclides% chem_id(pspecies(1)) == ih1 .and. &
     435            5 :                    nuclides% chem_id(pspecies(2)) == ih1 .and. &
     436              :                    nuclides% chem_id(pspecies(3)) == ih2) then
     437            5 :                   handle = 'r_h1_h1_ec_h2'
     438            5 :                   return
     439              :                end if
     440            7 :             else if (num_in == 1 .and. num_out == 1) then
     441            7 :                if (nuclides% chem_id(pspecies(1)) == ihe3 .and. &
     442              :                    nuclides% chem_id(pspecies(2)) == ih3) then
     443            5 :                   handle = 'r_he3_ec_h3'
     444            5 :                   return
     445              :                end if
     446            2 :                if (nuclides% chem_id(pspecies(1)) == ibe7 .and. &
     447              :                    nuclides% chem_id(pspecies(2)) == ili7) then
     448            2 :                   handle = 'r_be7_wk_li7'
     449            2 :                   return
     450              :                end if
     451              :             end if
     452       641947 :          else if (wk_flag) then
     453        73105 :             if (reverse) then
     454            0 :                handle = ''
     455            0 :                return
     456              :             end if
     457        73105 :             if (num_in == 2 .and. num_out == 1) then
     458              :                if (nuclides% chem_id(pspecies(1)) == ih1 .and. &
     459           10 :                    nuclides% chem_id(pspecies(2)) == ih1 .and. &
     460              :                    nuclides% chem_id(pspecies(3)) == ih2) then
     461            5 :                   handle = 'r_h1_h1_wk_h2'
     462            5 :                   return
     463              :                end if
     464        73095 :             else if (num_in == 2 .and. num_out == 1) then
     465              :                if (nuclides% chem_id(pspecies(1)) == ih1 .and. &
     466            0 :                    nuclides% chem_id(pspecies(2)) == ihe3 .and. &
     467              :                    nuclides% chem_id(pspecies(3)) == ihe4) then
     468            0 :                   handle = 'r_h1_he3_wk_he4'
     469            0 :                   return
     470              :                end if
     471              :             end if
     472              :          end if
     473              : 
     474       641942 :          in1 = 0; in2 = 0; out1 = 0; out2 = 0
     475       641942 :          do_long_form = .true.
     476       641942 :          if (num_in == 1 .and. num_out == 1) then
     477        36948 :             call do_n_to_m(1,1)
     478        36948 :             do_long_form = one_one()
     479       604994 :          else if (num_in == 1 .and. num_out == 2) then
     480        39465 :             call do_n_to_m(1,2)
     481        39465 :             if (reverse) then
     482        12260 :                do_long_form = two_one()
     483              :             else
     484        27205 :                do_long_form = one_two()
     485              :             end if
     486       565529 :          else if (num_in == 2 .and. num_out == 1) then
     487       249524 :             call do_n_to_m(2,1)
     488       249524 :             if (reverse) then
     489        79260 :                do_long_form = one_two()
     490              :             else
     491       170264 :                do_long_form = two_one()
     492              :             end if
     493       316005 :          else if (num_in == 2 .and. num_out == 2) then
     494       252034 :             call do_n_to_m(2,2)
     495       252034 :             do_long_form = two_two()
     496              :          end if
     497              : 
     498      1219930 :          if (do_long_form) then
     499       118991 :             call long_form
     500       522951 :          else if (out2 /= 0) then
     501       313513 :             handle = trim(handle) // '_' // nuclides% name(out2)
     502              :          else
     503       209438 :             handle = trim(handle) // '_' // nuclides% name(out1)
     504              :          end if
     505              : 
     506              : 
     507              :          contains
     508              : 
     509      1283918 :          subroutine sort(n, species)
     510              :             integer :: n
     511              :             integer :: species(n)
     512              :             integer :: i, j, Zi, Ni, Zj, Nj, isomer_j, isomer_i, cid
     513              :             include 'formats'
     514      2245969 :             do i=1,n-1
     515       962051 :                cid = species(i)
     516       962051 :                if (cid <= 0) cycle
     517       962051 :                Zi = chem_isos% Z(cid)
     518       962051 :                Ni = chem_isos% N(cid)
     519       962051 :                isomer_i = chem_isos% isomeric_state(cid)
     520      3313399 :                do j=i+1,n
     521      1067430 :                   cid = species(j)
     522      1067430 :                   if (cid <= 0) cycle
     523      1067430 :                   Zj = chem_isos% Z(cid)
     524      1067430 :                   Nj = chem_isos% N(cid)
     525      1067430 :                   isomer_j = chem_isos% isomeric_state(cid)
     526      1067430 :                   if (Zj > Zi) cycle
     527       166055 :                   if (Zj == Zi) then
     528       166005 :                      if (Nj > Ni) cycle
     529       165915 :                      if (Nj == Ni) then
     530       165885 :                         if (isomer_j >= isomer_i) cycle
     531              :                      end if
     532              :                   end if
     533              :                   ! exchange i and j
     534           80 :                   species(j) = species(i)
     535           80 :                   species(i) = cid
     536           80 :                   Zi = Zj
     537           80 :                   Ni = Nj
     538      2029481 :                   isomer_i = isomer_j
     539              :                end do
     540              :             end do
     541       641959 :          end subroutine sort
     542              : 
     543       118991 :          subroutine long_form
     544              :             integer :: i, cid
     545              :             character (len=3) :: op
     546       118991 :             handle = 'r_'
     547       118991 :             if (wk_flag) then
     548        37865 :                op = 'wk_'
     549        81126 :             else if (ec_flag) then
     550            0 :                op = 'ec_'
     551              :             else
     552        81126 :                op = 'to_'
     553              :             end if
     554       118991 :             if (reverse) then
     555         1255 :                do i = num_in+1,num_in+num_out
     556          875 :                   cid = pspecies(i)
     557         1255 :                   handle = trim(handle) // trim(nuclides% name(cid)) // '_'
     558              :                end do
     559          380 :                handle = trim(handle) // op
     560         1195 :                do i = 1,num_in
     561          815 :                   cid = pspecies(i)
     562          815 :                   handle = trim(handle) // trim(nuclides% name(cid))
     563         1195 :                   if (i < num_in) handle = trim(handle) // '_'
     564              :                end do
     565              :             else
     566       338066 :                do i = 1,num_in
     567       219455 :                   cid = pspecies(i)
     568       338066 :                   handle = trim(handle) // trim(nuclides% name(cid)) // '_'
     569              :                end do
     570       118611 :                handle = trim(handle) // op
     571       390093 :                do i = num_in+1,num_in+num_out
     572       271482 :                   cid = pspecies(i)
     573       271482 :                   handle = trim(handle) // trim(nuclides% name(cid))
     574       390093 :                   if (i < num_in+num_out) handle = trim(handle) // '_'
     575              :                end do
     576              :             end if
     577       118991 :          end subroutine long_form
     578              : 
     579        36948 :          logical function one_one()
     580        36948 :             one_one = .true.
     581        36948 :             if (in1 == 0 .or. out1 == 0) return
     582        36948 :             one_one = .false.
     583        36948 :             if (nuclides% Z(out1) == nuclides% Z(in1) - 1 .and. &
     584              :                 nuclides% N(out1) == nuclides% N(in1) + 1) then
     585        10708 :                handle = trim(handle) // '_wk'
     586        26240 :             else if (nuclides% Z(out1) == nuclides% Z(in1) + 1 .and. &
     587              :                      nuclides% N(out1) == nuclides% N(in1) - 1) then
     588        26240 :                handle = trim(handle) // '_wk-minus'
     589              :             else
     590              :                one_one = .true.
     591              :             end if
     592              :          end function one_one
     593              : 
     594       106465 :          logical function one_two()
     595       106465 :             one_two = .true.
     596       106465 :             if (in1 == 0 .or. out1 == 0 .or. out2 == 0 .or. out1 == out2) return
     597       106450 :             one_two = .false.
     598              :             if (nuclides% Z(out1) == 0 .and. nuclides% N(out1) == 1 .and. &
     599       106450 :                      nuclides% Z(out2) == nuclides% Z(in1) .and. &
     600              :                      nuclides% N(out2) == nuclides% N(in1) - 1) then
     601        36775 :                handle = trim(handle) // '_gn'
     602              :             else if (nuclides% Z(out1) == 1 .and. nuclides% N(out1) == 0 .and. &
     603        69675 :                      nuclides% Z(out2) == nuclides% Z(in1) - 1 .and. &
     604              :                      nuclides% N(out2) == nuclides% N(in1)) then
     605        26265 :                handle = trim(handle) // '_gp'
     606              :             else if (nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     607        43410 :                      nuclides% Z(out2) == nuclides% Z(in1) - 2 .and. &
     608              :                      nuclides% N(out2) == nuclides% N(in1) - 2) then
     609        28470 :                handle = trim(handle) // '_ga'
     610              :             else if (nuclides% Z(out1) == 1 .and. nuclides% N(out1) == 0 .and. &
     611        14940 :                      nuclides% Z(out2) == nuclides% Z(in1) - 2 .and. &
     612              :                      nuclides% N(out2) == nuclides% N(in1) + 1) then
     613          540 :                handle = trim(handle) // '_wk_h1'
     614              :             else if (nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     615        14400 :                      nuclides% Z(out2) == nuclides% Z(in1) - 3 .and. &
     616              :                      nuclides% N(out2) == nuclides% N(in1) - 1) then
     617           70 :                handle = trim(handle) // '_wk_he4'
     618              :             else
     619              :                one_two = .true.
     620              :             end if
     621              :          end function one_two
     622              : 
     623       182524 :          logical function two_one()
     624              :             include 'formats'
     625       182524 :             two_one = .true.
     626       182524 :             if (in1 == 0 .or. in2 == 0 .or. out1 == 0 .or. in1 == in2) return
     627       172500 :             two_one = .false.
     628              :             if (nuclides% Z(in1) == 0 .and. nuclides% N(in1) == 1 .and. &
     629       172500 :                      nuclides% Z(out1) == nuclides% Z(in2) .and. &
     630              :                      nuclides% N(out1) == nuclides% N(in2) + 1) then
     631        36937 :                handle = trim(handle) // '_ng'
     632              :             else if (nuclides% Z(in1) == 1 .and. nuclides% N(in1) == 0 .and. &
     633       135563 :                      nuclides% Z(out1) == nuclides% Z(in2) + 1 .and. &
     634              :                      nuclides% N(out1) == nuclides% N(in2)) then
     635        76972 :                handle = trim(handle) // '_pg'
     636              :             else if (nuclides% Z(in1) == 2 .and. nuclides% N(in1) == 2 .and. &
     637        58591 :                      nuclides% Z(out1) == nuclides% Z(in2) + 2 .and. &
     638              :                      nuclides% N(out1) == nuclides% N(in2) + 2) then
     639        58581 :                handle = trim(handle) // '_ag'
     640              :             else
     641              :                two_one = .true.
     642              :             end if
     643              :          end function two_one
     644              : 
     645       252034 :          logical function two_two()
     646       252034 :             two_two = .true.
     647              : 
     648       252034 :             if (in1 == 0 .or. in2 == 0 .or. out1 == 0 .or. out2 == 0) return
     649              : 
     650              :             ! Special case r_li7_pa_he4, this must come first otherwise the out1==out2
     651              :             ! check will label this rate as a _to_ reaction instead of an _ap reaction
     652              :             if (nuclides% Z(in1) == 1 .and. nuclides% N(in1) == 0 .and. &
     653              :                nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     654              :                nuclides% Z(out2) == 2 .and.  nuclides% N(out2) == 2 .and. &
     655       252034 :                nuclides% Z(in2) == 3 .and. nuclides% N(in2) == 4) then
     656           20 :                handle = trim(handle) // '_pa'
     657           20 :                two_two = .false.
     658           20 :                return
     659              :             end if
     660              : 
     661       252014 :             if(in1==in2 .or. out1==out2) return
     662              : 
     663       231704 :             two_two = .false.
     664              :             if (nuclides% Z(in1) == 2 .and. nuclides% N(in1) == 2 .and. &
     665              :                      nuclides% Z(out1) == 1 .and. nuclides% N(out1) == 0 .and. &
     666       231704 :                      nuclides% Z(out2) == nuclides% Z(in2) + 1 .and. &
     667              :                      nuclides% N(out2) == nuclides% N(in2) + 2) then
     668        35632 :                handle = trim(handle) // '_ap'
     669              :             else if (nuclides% Z(in1) == 1 .and. nuclides% N(in1) == 0 .and. &
     670              :                      nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     671       196072 :                      nuclides% Z(out2) == nuclides% Z(in2) - 1 .and. &
     672              :                      nuclides% N(out2) == nuclides% N(in2) - 2) then
     673        85799 :                 handle = trim(handle) // '_pa'
     674              :             else if (nuclides% Z(in1) == 2 .and. nuclides% N(in1) == 2 .and. &
     675              :                      nuclides% Z(out1) == 0 .and. nuclides% N(out1) == 1 .and. &
     676       110273 :                      nuclides% Z(out2) == nuclides% Z(in2) + 2 .and. &
     677              :                      nuclides% N(out2) == nuclides% N(in2) + 1) then
     678        24995 :                 handle = trim(handle) // '_an'
     679              :             else if (nuclides% Z(in1) == 0 .and. nuclides% N(in1) == 1 .and. &
     680              :                      nuclides% Z(out1) == 2 .and. nuclides% N(out1) == 2 .and. &
     681        85278 :                      nuclides% Z(out2) == nuclides% Z(in2) - 2 .and. &
     682              :                      nuclides% N(out2) == nuclides% N(in2) - 1) then
     683        25067 :                 handle = trim(handle) // '_na'
     684              :             else if (nuclides% Z(in1) == 1 .and. nuclides% N(in1) == 0 .and. &
     685              :                      nuclides% Z(out1) == 0 .and. nuclides% N(out1) == 1 .and. &
     686        60211 :                      nuclides% Z(out2) == nuclides% Z(in2) + 1 .and. &
     687              :                      nuclides% N(out2) == nuclides% N(in2) - 1) then
     688        24940 :                 handle = trim(handle) // '_pn'
     689              :             else if (nuclides% Z(in1) == 0 .and. nuclides% N(in1) == 1 .and. &
     690              :                      nuclides% Z(out1) == 1 .and. nuclides% N(out1) == 0 .and. &
     691        35271 :                      nuclides% Z(out2) == nuclides% Z(in2) - 1 .and. &
     692              :                      nuclides% N(out2) == nuclides% N(in2) + 1) then
     693        24940 :                 handle = trim(handle) // '_np'
     694              :             else
     695              :                two_two = .true.
     696              :             end if
     697              :          end function two_two
     698              : 
     699       577971 :          subroutine do_n_to_m(n,m)
     700              :             integer, intent(in) :: n, m  ! each is either 1 or 2
     701       577971 :             in1 = 0; in2 = 0; out1 = 0; out2 = 0
     702       577971 :             if (.not. reverse) then
     703       411006 :                in1 = pspecies(1)
     704       411006 :                if (n == 2) then
     705       346853 :                   in2 = pspecies(2)
     706       346853 :                   if (in2 == 0) then
     707            0 :                      in1 = 0; return
     708              :                   end if
     709       346853 :                   call switch_if_necessary(in1,in2)
     710       346853 :                   handle = 'r_' // nuclides% name(in2)
     711        64153 :                else if (n == 1) then
     712        64153 :                   handle = 'r_' // nuclides% name(in1)
     713              :                else
     714            0 :                   in1 = 0
     715            0 :                   return
     716              :                end if
     717       411006 :                out1 = pspecies(n+1)
     718       411006 :                if (m == 2) then
     719       203794 :                   out2 = pspecies(n+2)
     720       203794 :                   call switch_if_necessary(out1,out2)
     721              :                end if
     722              :             else
     723       166965 :                in1 = pspecies(n+1)
     724       166965 :                if (m == 2) then
     725        87705 :                   in2 = pspecies(n+2)
     726        87705 :                   if (in2 == 0) then
     727            0 :                      in1 = 0; return
     728              :                   end if
     729        87705 :                   call switch_if_necessary(in1,in2)
     730        87705 :                   handle = 'r_' // nuclides% name(in2)
     731        79260 :                else if (m == 1) then
     732        79260 :                   handle = 'r_' // nuclides% name(in1)
     733              :                else
     734            0 :                   in1 = 0
     735            0 :                   return
     736              :                end if
     737       166965 :                out1 = pspecies(1)
     738       166965 :                if (n == 2) then
     739       154705 :                   out2 = pspecies(2)
     740       154705 :                   call switch_if_necessary(out1,out2)
     741              :                end if
     742              :             end if
     743              :          end subroutine do_n_to_m
     744              : 
     745       793057 :          subroutine switch_if_necessary(iso1,iso2)
     746              :             integer, intent(inout) :: iso1, iso2
     747              :             integer :: j
     748       793057 :             if (nuclides% Z(iso2) == 1 .and. nuclides% N(iso2) == 0) then  ! iso2 is ih1
     749           30 :                j = iso1; iso1 = iso2; iso2 = j; return
     750              :             end if
     751       793027 :             if (nuclides% Z(iso2) == 2 .and. nuclides% N(iso2) == 2) then  ! iso2 is ihe4
     752        10209 :                if (nuclides% Z(iso1) == 1 .and. nuclides% N(iso1) == 0) return  ! iso1 is ih1
     753          170 :                j = iso1; iso1 = iso2; iso2 = j; return
     754              :             end if
     755              :          end subroutine switch_if_necessary
     756              : 
     757              : 
     758              :       end subroutine get1_reaction_handle
     759              : 
     760              : 
     761              :       end module reaclib_support
        

Generated by: LCOV version 2.0-1