tw_rate_module.f90
Go to the documentation of this file.
1 !> @file tw_rate_module.f90
2 !!
3 !! The error file code for this file is ***W44***.
4 !!
5 !! Contains the module \ref tw_rate_module.
6 
7 
8 !>
9 !! @brief This module contains everything for the theoretical weak rates that
10 !! are added into the rate array
11 !!
12 !! The theoretical weak rates in the current form were implemented by M. Ugliano.
13 !! They contain electron captures and beta decays.
14 !! Rates that are contained in the weak rate file and in reaclib
15 !! get replaced by the ones contained in weak rates for small
16 !! temperatures (see parameter_class::temp_reload_exp_weak_rates).
17 !!
18 !! @see [Langanke & Martinez-Pinedo 2001](https://ui.adsabs.harvard.edu/abs/2001ADNDT..79....1L/abstract),
19 !! [Fuller et al. 1985](https://ui.adsabs.harvard.edu/abs/1985ApJ...293....1F/abstract),
20 !! [Oda et al. 1994](https://ui.adsabs.harvard.edu/abs/1994ADNDT..56..231O/abstract),
21 !! [Weak rate library](https://groups.nscl.msu.edu/charge_exchange/weakrates.html)
22 #include "macros.h"
25  implicit none
26 
27 
28  !> data fields for weak rates given in Langanke&Martinez-Pinedo 2001
29  type,private :: weakrate_type
30  integer,dimension(2) :: parts !< isotope index of participants [1:2]
31  logical :: is_ec !< true if reaction is electron capture reaction
32  character(4) :: source !< source of reaction rate
33  integer :: n_points !< total amount of grid_points
34  integer :: n_temp_grid !< Length of temperature grid
35  integer :: n_rho_grid !< Length of density grid
36  real(r_kind) :: q_value !< reaction Q-value [MeV]
37  real(r_kind) :: min_rho,max_rho !< min and max rho*ye
38  real(r_kind) :: min_temp,max_temp !< min and max temp
39  real(r_kind),dimension(:),allocatable :: temp_grid !< temperature grid for tabulation
40  real(r_kind),dimension(:),allocatable :: rho_grid !< rho*ye grid for tabulation
41  real(r_kind),dimension(:,:),allocatable:: mue_kin !< Electron chemical potential (only kinetic, no rest mass)
42  real(r_kind),dimension(:,:),allocatable:: dmue_kin_dt !< Temperature derivative of the chemical potential
43  real(r_kind),dimension(:,:),allocatable:: dmue_kin_dr !< Density derivative of the chemical potential
44  real(r_kind),dimension(:,:),allocatable:: dmue_kin_dt_dr !< Mixed partial derivative of the chemical potential
45  real(r_kind),dimension(:,:),allocatable:: beta_rate !< tabulated beta decay rates
46  real(r_kind),dimension(:,:),allocatable:: dbeta_dt !< Temperature derivative of the beta rate
47  real(r_kind),dimension(:,:),allocatable:: dbeta_dr !< Density derivative of the beta rate
48  real(r_kind),dimension(:,:),allocatable:: dbeta_dt_dr !< Mixed partial derivative of the beta rate
49  real(r_kind),dimension(:,:),allocatable:: ft_rate !< tabulated log<ft> electron/positron capture rates
50  real(r_kind),dimension(:,:),allocatable:: dft_dt !< Temperature derivative of the log<ft> rates
51  real(r_kind),dimension(:,:),allocatable:: dft_dr !< Density derivative of the log<ft>
52  real(r_kind),dimension(:,:),allocatable:: dft_dt_dr !< Mixed partial derivative of the log<ft>
53  real(r_kind),dimension(:,:),allocatable:: nu_loss !< tabulated energy loss due to (anti-)neutrino emission
54  end type weakrate_type
55 
56  type(weakrate_type),dimension(:),allocatable,public :: weak_rate !< array containing the weak reactions
57 
58  logical,public :: weak !< switch for weak rates
59  integer,private :: nweak !< number of weak reactions taken from Langanke&Martinez-pinedo
60  type(reactionrate_type), dimension(:), allocatable,private :: rrate_weak !< Reaction rate representative in global_class::rrate
61  integer,dimension(2,2) , private :: wk_index !< Multi-index for the weak rates
62  real(r_kind),public :: mue !< chemical potential of the electron
63  integer,parameter,private :: mue_ident=1 !< Identifier for chemical potential
64  integer,parameter,private :: beta_ident=2 !< Identifier for beta rate
65  integer,parameter,private :: ft_ident=3 !< Identifier for forward rate
66  integer,parameter,private :: nu_loss_ident=4 !< Identifier for the neutrino loss
67 
68  integer,private :: n_ec, n_o !< individual reaction types
69  character(len=*), private, parameter :: weak_binary_name='weak_rates.windat' !< Filename of binary file to save weak rates
70  !
71  ! Public and private fields and methods of the module
72  !
73  public:: &
76  private:: &
79 
80 contains
81 
82 
83  !> Initialize theoretical weak rates
84  !!
85  !! This subroutine set the flag weak and calls
86  !! the necessary subroutines to read the rates.
87  !!
88  !! @author Moritz Reichert
89  !! @date 24.01.21
93  implicit none
94 
95  ! Set the amount to zero, later it is set in readweak_logft
96  nweak = 0
97  ! Set default for individual reactions
98  n_ec=0; n_o=0
99 
100  weak= (iwformat.ne.0)
101 
102  if (weak) then
103  if (use_prepared_network) then
105  else
108  end if
109  ! Output info
111  call output_n_p()
112  end if
113  end subroutine init_theoretical_weak_rates
114 
115 
116  !> Calculate derivatives of weak reactions
117  !!
118  !! These derivatives are necessary for the bicubic interpolation.
119  !!
120  !! @author: M. Reichert
124  implicit none
125  integer :: nt,nr !< Number of temperature and rho points
126  integer :: i !< Loop variable
127 
128  ! (Bi-)Cubic interpolation
129  if (iwinterp .eq. 1) then
130  do i=1, nweak
131  nt = weak_rate(i)%n_temp_grid
132  nr = weak_rate(i)%n_rho_grid
133  ! Allocate arrays
134  allocate(weak_rate(i)%dbeta_dT(nt,nr),&
135  weak_rate(i)%dbeta_dR(nt,nr),&
136  weak_rate(i)%dbeta_dT_dR(nt,nr),&
137  weak_rate(i)%dft_dT(nt,nr),&
138  weak_rate(i)%dft_dR(nt,nr),&
139  weak_rate(i)%dft_dT_dR(nt,nr) )
140 
141  ! Calculate derivatives
142  call calc_derivative_2d(weak_rate(i)%beta_rate,weak_rate(i)%temp_grid,&
143  weak_rate(i)%rho_grid,weak_rate(i)%dbeta_dT,&
144  weak_rate(i)%dbeta_dR,weak_rate(i)%dbeta_dT_dR,&
145  nt,nr)
146  call calc_derivative_2d(weak_rate(i)%ft_rate,weak_rate(i)%temp_grid,&
147  weak_rate(i)%rho_grid,weak_rate(i)%dft_dT,&
148  weak_rate(i)%dft_dR,weak_rate(i)%dft_dT_dR,&
149  nt,nr)
150  end do
151  end if
152 
153  ! The chemical potential should be interpolated bicubic
154  if (.not. use_timmes_mue) then
155  do i=1, nweak
156  nt = weak_rate(i)%n_temp_grid
157  nr = weak_rate(i)%n_rho_grid
158  ! Allocate arrays
159  allocate(weak_rate(i)%dmue_kin_dT(nt,nr),&
160  weak_rate(i)%dmue_kin_dR(nt,nr),&
161  weak_rate(i)%dmue_kin_dT_dR(nt,nr))
162  ! Calculate derivatives
163  call calc_derivative_2d(weak_rate(i)%mue_kin,weak_rate(i)%temp_grid,&
164  weak_rate(i)%rho_grid,weak_rate(i)%dmue_kin_dT,&
165  weak_rate(i)%dmue_kin_dR,weak_rate(i)%dmue_kin_dT_dR,&
166  nt,nr)
167  end do
168  end if
169 
170  end subroutine initialize_cubic_interp
171 
172 
173  !> Write the amount of individual reactions to the out
174  !!
175  !! The rates are always counted, for a certain verbose level they
176  !! are also printed to the OUT file
177  !!
178  !! @author M. Reichert
179  !! @date 27.01.21
182  implicit none
183  character(len=7) :: tmp !< temporary character for pretty output
184 
185  if (verbose_level .ge. 1) then
186  call write_data_to_std_out("Amount weak (ffn) rates",int_to_str(nweak))
187  elseif (verbose_level .ge. 2) then
188  if (nweak .gt. 0) write(*,"(A)") ""
189  if (nweak .gt. 0) write(*,"(A)")" FFN rates: "
190  if (nweak .gt. 0) write(*,"(A)")" |---------------------------|"
191  tmp = int_to_str(nweak)
192  if (nweak .gt. 0) write(*,"(A)")" | Total :"//adjustr(tmp)//" |"
193  tmp = int_to_str(n_ec)
194  if (n_ec .gt. 0) write(*,"(A)") " | Electron-capture :"//adjustr(tmp)//" |"
195  tmp = int_to_str(n_o)
196  if (n_o .gt. 0) write(*,"(A)") " | Beta-decay :"//adjustr(tmp)//" |"
197  if (nweak .gt. 0)write(*,"(A)") " |---------------------------|"
198  if (nweak .gt. 0)write(*,"(A)") ""
199  end if
200 
201  end subroutine write_reac_verbose_out
202 
203 
204  !> Merge theoretical weak rates into larger rate array.
205  !!
206  !! This merge is partly done instantaneously and partly when
207  !! the temperature reaches parameter_class::reload_exp_weak_rates.
208  subroutine merge_theoretical_weak_rates(rrate_array,rrate_length)
213  implicit none
214  type(reactionrate_type),dimension(:),allocatable,intent(inout) :: rrate_array !< Large rate array, containing all reactions
215  integer,intent(inout) :: rrate_length !< length of rrate_array
216  type(reactionrate_type),dimension(:),allocatable :: rrate_tmp !< Temporary rate array
217  integer :: alloc_stat !< Allocation state
218  integer :: new_length !< New length of the array
219 
220  if (weak .and. (.not. use_prepared_network)) then
221  if (.not. allocated(rrate_array)) then
222  !-- Allocate the reaclib rate array
223  allocate(rrate_array(nweak),stat=alloc_stat)
224  if ( alloc_stat /= 0) call raise_exception('Allocation of "rrate_array" failed.',&
225  "merge_theoretical_weak_rates",440001)
226  rrate_array(1:nweak) = rrate_weak(1:nweak)
227  rrate_length = nweak
228  else
229  call rrate_sort(rrate_length,rrate_array(1:rrate_length))
232  !----- merge weak rates into rrate
233  call rrate_ms(rrate_array(1:rrate_length),rrate_length,rrate_weak,&
234  size(rrate_weak),1,new_length,rrate_tmp)
235  rrate_length = new_length
236  ! Reallocate rrate_array with new length
237  if (allocated(rrate_array)) deallocate(rrate_array)
238  allocate(rrate_array(rrate_length),stat=alloc_stat)
239  if ( alloc_stat /= 0) call raise_exception('Allocation of "rrate_array" failed.',&
240  "merge_theoretical_weak_rates",440001)
241  rrate_array(1:rrate_length) = rrate_tmp(1:rrate_length)
242  end if
243  !-- Deallocate the reaclib rate array
244  deallocate(rrate_weak)
245  end if
246 
247  end subroutine merge_theoretical_weak_rates
248 
249 
250 
251 
252 
253  !> Read the theoretical weak rates from a unformatted binary file
254  !!
255  !! In case the binary file is read, no other data has to be read.
256  !!
257  !! @author M. Reichert
258  !! @date 27.07.21
264  implicit none
265  character(len=*), intent(in) :: path !< Path to binary file
266  integer :: file_id !< File identifier
267  integer :: i !< Loop variable
268  logical :: allocated_or_not!< Logical to check if array is allocated
269  integer :: status !< Status of allocation
270 
271 
272  file_id = open_unformatted_infile(trim(adjustl(path))//trim(adjustl(weak_binary_name)))
273 
274  read(file_id) nweak
275  read(file_id) n_ec
276  read(file_id) n_o
277  read(file_id) common_weak_rates
278  read(file_id) only_theo_weak_rates
279 
280  allocate(weak_rate(nweak),stat=status)
281  if (status /= 0) call raise_exception('Allocation of "weak_rate" failed.',&
282  "read_binary_weak_reaction_data",440001)
283 
284  do i=1, nweak
285  read(file_id) weak_rate(i)%parts
286  read(file_id) weak_rate(i)%is_ec
287  read(file_id) weak_rate(i)%source
288  read(file_id) weak_rate(i)%n_points
289  read(file_id) weak_rate(i)%n_temp_grid
290  read(file_id) weak_rate(i)%n_rho_grid
291  read(file_id) weak_rate(i)%q_value
292  read(file_id) weak_rate(i)%min_rho
293  read(file_id) weak_rate(i)%max_rho
294  read(file_id) weak_rate(i)%min_temp
295  read(file_id) weak_rate(i)%max_temp
296  read(file_id) allocated_or_not
297  if (allocated_or_not) then
298  allocate(weak_rate(i)%temp_grid(weak_rate(i)%n_temp_grid))
299  read(file_id) weak_rate(i)%temp_grid
300  end if
301  read(file_id) allocated_or_not
302  if (allocated_or_not) then
303  allocate(weak_rate(i)%rho_grid(weak_rate(i)%n_rho_grid))
304  read(file_id) weak_rate(i)%rho_grid
305  end if
306  read(file_id) allocated_or_not
307  if (allocated_or_not) then
308  allocate(weak_rate(i)%mue_kin(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
309  read(file_id) weak_rate(i)%mue_kin
310  end if
311  read(file_id) allocated_or_not
312  if (allocated_or_not) then
313  allocate(weak_rate(i)%dmue_kin_dT(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
314  read(file_id) weak_rate(i)%dmue_kin_dT
315  end if
316  read(file_id) allocated_or_not
317  if (allocated_or_not) then
318  allocate(weak_rate(i)%dmue_kin_dR(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
319  read(file_id) weak_rate(i)%dmue_kin_dR
320  end if
321  read(file_id) allocated_or_not
322  if (allocated_or_not) then
323  allocate(weak_rate(i)%dmue_kin_dT_dR(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
324  read(file_id) weak_rate(i)%dmue_kin_dT_dR
325  end if
326  read(file_id) allocated_or_not
327  if (allocated_or_not) then
328  allocate(weak_rate(i)%beta_rate(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
329  read(file_id) weak_rate(i)%beta_rate
330  end if
331  read(file_id) allocated_or_not
332  if (allocated_or_not) then
333  allocate(weak_rate(i)%dbeta_dT(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
334  read(file_id) weak_rate(i)%dbeta_dT
335  end if
336  read(file_id) allocated_or_not
337  if (allocated_or_not) then
338  allocate(weak_rate(i)%dbeta_dR(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
339  read(file_id) weak_rate(i)%dbeta_dR
340  end if
341  read(file_id) allocated_or_not
342  if (allocated_or_not) then
343  allocate(weak_rate(i)%dbeta_dT_dR(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
344  read(file_id) weak_rate(i)%dbeta_dT_dR
345  end if
346  read(file_id) allocated_or_not
347  if (allocated_or_not) then
348  allocate(weak_rate(i)%ft_rate(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
349  read(file_id) weak_rate(i)%ft_rate
350  end if
351  read(file_id) allocated_or_not
352  if (allocated_or_not) then
353  allocate(weak_rate(i)%dft_dT(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
354  read(file_id) weak_rate(i)%dft_dT
355  end if
356  read(file_id) allocated_or_not
357  if (allocated_or_not) then
358  allocate(weak_rate(i)%dft_dR(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
359  read(file_id) weak_rate(i)%dft_dR
360  end if
361  read(file_id) allocated_or_not
362  if (allocated_or_not) then
363  allocate(weak_rate(i)%dft_dT_dR(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
364  read(file_id) weak_rate(i)%dft_dT_dR
365  end if
366  read(file_id) allocated_or_not
367  if (allocated_or_not) then
368  allocate(weak_rate(i)%nu_loss(weak_rate(i)%n_temp_grid,weak_rate(i)%n_rho_grid))
369  read(file_id) weak_rate(i)%nu_loss
370  end if
371  end do
372 
373  read(file_id) common_weak_rates
374  allocate(rrate_weak_exp(common_weak_rates),stat=status)
375  if (status /= 0) call raise_exception('Allocation of "rrate_weak_exp" failed.',&
376  "read_binary_weak_reaction_data",440001)
377  read(file_id) rrate_weak_exp
378 
379  close(file_id)
380 
381  end subroutine read_binary_weak_reaction_data
382 
383 
384 
385 
386  !> Save the theoretical weak rates to a unformatted binary file
387  !!
388  !! @author M. Reichert
389  !! @date 27.07.21
394  implicit none
395  character(len=*), intent(in) :: path
396  integer :: i
397  integer :: file_id
398 
399  if (.not. weak) return
400 
401  ! Open an unformatted file
402  file_id = open_unformatted_outfile(trim(adjustl(path))//trim(adjustl(weak_binary_name)))
403  ! Save the data
404  write(file_id) nweak
405  write(file_id) n_ec
406  write(file_id) n_o
407  write(file_id) common_weak_rates
408  write(file_id) only_theo_weak_rates
409 
410 
411  do i=1,nweak
412  ! First write all things that are not allocatable
413  write(file_id) weak_rate(i)%parts
414  write(file_id) weak_rate(i)%is_ec
415  write(file_id) weak_rate(i)%source
416  write(file_id) weak_rate(i)%n_points
417  write(file_id) weak_rate(i)%n_temp_grid
418  write(file_id) weak_rate(i)%n_rho_grid
419  write(file_id) weak_rate(i)%q_value
420  write(file_id) weak_rate(i)%min_rho
421  write(file_id) weak_rate(i)%max_rho
422  write(file_id) weak_rate(i)%min_temp
423  write(file_id) weak_rate(i)%max_temp
424  ! Now take care of allocatable parts
425  write(file_id) allocated(weak_rate(i)%temp_grid)
426  if (allocated(weak_rate(i)%temp_grid)) write(file_id) weak_rate(i)%temp_grid
427  write(file_id) allocated(weak_rate(i)%rho_grid)
428  if (allocated(weak_rate(i)%rho_grid)) write(file_id) weak_rate(i)%rho_grid
429  write(file_id) allocated(weak_rate(i)%mue_kin)
430  if (allocated(weak_rate(i)%mue_kin)) write(file_id) weak_rate(i)%mue_kin
431  write(file_id) allocated(weak_rate(i)%dmue_kin_dT)
432  if (allocated(weak_rate(i)%dmue_kin_dT)) write(file_id) weak_rate(i)%dmue_kin_dT
433  write(file_id) allocated(weak_rate(i)%dmue_kin_dR)
434  if (allocated(weak_rate(i)%dmue_kin_dR)) write(file_id) weak_rate(i)%dmue_kin_dR
435  write(file_id) allocated(weak_rate(i)%dmue_kin_dT_dR)
436  if (allocated(weak_rate(i)%dmue_kin_dT_dR)) write(file_id) weak_rate(i)%dmue_kin_dT_dR
437  write(file_id) allocated(weak_rate(i)%beta_rate)
438  if (allocated(weak_rate(i)%beta_rate)) write(file_id) weak_rate(i)%beta_rate
439  write(file_id) allocated(weak_rate(i)%dbeta_dT)
440  if (allocated(weak_rate(i)%dbeta_dT)) write(file_id) weak_rate(i)%dbeta_dT
441  write(file_id) allocated(weak_rate(i)%dbeta_dR)
442  if (allocated(weak_rate(i)%dbeta_dR)) write(file_id) weak_rate(i)%dbeta_dR
443  write(file_id) allocated(weak_rate(i)%dbeta_dT_dR)
444  if (allocated(weak_rate(i)%dbeta_dT_dR)) write(file_id) weak_rate(i)%dbeta_dT_dR
445  write(file_id) allocated(weak_rate(i)%ft_rate)
446  if (allocated(weak_rate(i)%ft_rate)) write(file_id) weak_rate(i)%ft_rate
447  write(file_id) allocated(weak_rate(i)%dft_dT)
448  if (allocated(weak_rate(i)%dft_dT)) write(file_id) weak_rate(i)%dft_dT
449  write(file_id) allocated(weak_rate(i)%dft_dR)
450  if (allocated(weak_rate(i)%dft_dR)) write(file_id) weak_rate(i)%dft_dR
451  write(file_id) allocated(weak_rate(i)%dft_dT_dR)
452  if (allocated(weak_rate(i)%dft_dT_dR)) write(file_id) weak_rate(i)%dft_dT_dR
453  write(file_id) allocated(weak_rate(i)%nu_loss)
454  if (allocated(weak_rate(i)%nu_loss)) write(file_id) weak_rate(i)%nu_loss
455  end do
456 
457  ! Now output also the expermental rates rrate_weak_exp
458  write(file_id) common_weak_rates
459  write(file_id) rrate_weak_exp
460 
461  close(file_id)
462 
463 
464  end subroutine output_binary_weak_reaction_data
465 
466 
467 
468 
469  !> Calculate the theoretical weak rate.
470  !!
471  !! For \ref parameter_class::iwformat equal to 1, this routine interpolates
472  !! the rate on the temperature - density grid. Otherwise, for parameter_class::iwformat
473  !! equal 2, this subroutine calculates the effective phase space integral to translate
474  !! the tabulated log <ft> values to actual rates. For this also the chemical
475  !! potential has to be known.
476  !!
477  !! \b Edited:
478  !! - 26.07.22, MR: Created this subroutine from previously existing code in Jacobi_init
479  !! .
480  !!
481  !! @warning In case of \ref parameter_class::iwformat equal to two
482  !! and using timmes chemical potential (\ref parameter_class::use_timmes_mue)
483  !! \ref mue has to be calculated prior to calling this subroutine.
484  subroutine calculate_twr_rate(rrate, temp, rho, Ye, rat_calc, nuloss)
486  use effphase_class, only: effphase
487  implicit none
488  type(reactionrate_type),intent(inout):: rrate !< rate instance
489  real(r_kind),intent(in) :: temp !< Temperature [GK]
490  real(r_kind),intent(in) :: rho !< Density [g/ccm]
491  real(r_kind),intent(in) :: ye !< Electron fraction
492  real(r_kind),intent(out) :: rat_calc !< rate value
493  logical,optional :: nuloss !< calculate neutrino loss?
494  ! Internal variables
495  integer :: wind !< Weak index
496  real(r_kind) :: rbeta,rft,repsi,rnu
497  real(r_kind) :: epsi !< effective phase-space integral
498  logical :: is_ec !< flag for electron captures
499 
500  ! Set default value of neutrino loss
501  rrate%nu_frac = heating_frac
502 
503  ! weak_index determines the cornerpoints for the temp and dens interpolation
504  wind = int(rrate%param(1))
505  call weak_index (temp, rho, ye, weak_rate(wind))
506  is_ec = weak_rate(wind)%is_ec
507  ! weak_inter interpolates the weak rate using the result from weak_index
508  ! for weak rates rrate(i)%param gives the index of the rate in weak_rate array
509  if (iwformat .eq. 1) then
510  rft = weak_inter(ft_ident,temp,dlog10(rho*ye),weak_rate(wind))
511  rbeta = weak_inter(beta_ident,temp,dlog10(rho*ye),weak_rate(wind))
512  if (present(nuloss)) then
513  if (nuloss) then
514  rnu = weak_inter(nu_loss_ident,temp,dlog10(rho*ye),weak_rate(wind))
515  rnu = rnu/(rft+rbeta)
516  end if
517  end if
518  rat_calc = rft+rbeta
519  else if (iwformat .eq. 2) then
520  ! Use the electron chemical potential directly from the rate file
521  if (.not. use_timmes_mue) then
522  mue = weak_inter(mue_ident,temp,dlog10(rho*ye),weak_rate(wind),.true.)
523  mue = dlog10(mue)+ unit%mass_e
524  end if
525  rft = weak_inter(ft_ident,temp,dlog10(rho*ye),weak_rate(wind))
526  rbeta = weak_inter(beta_ident,temp,dlog10(rho*ye),weak_rate(wind))
527  if (present(nuloss)) then
528  if (nuloss) then
529  rnu = weak_inter(nu_loss_ident,temp,dlog10(rho*ye),weak_rate(wind))
530  end if
531  end if
532  if (is_ec) then
533  call effphase(temp,mue,weak_rate(wind)%q_value,epsi)
534  else
535  call effphase(temp,-mue,weak_rate(wind)%q_value,epsi)
536  end if
537  if ((epsi.lt.1.d-100).or.(rft.le.9.d-99)) then
538  repsi = 1.d-100
539  else
540  repsi = dlog(2.d0)*epsi/rft
541  end if
542 
543 
544  ! total rate = beta rate + ft-rate
545  rat_calc = repsi + rbeta
546  end if
547 
548  ! Calculate neutrino loss fractions
549  ! Note that the fraction can be larger than one
550  if (present(nuloss)) then
551  if (nuloss) then
552  ! This can also be negative, but later on it is multiplied by the
553  ! q-value again
554  rrate%nu_frac = rnu/rrate%q_value
555  end if
556  end if
557 
558 
559  end subroutine calculate_twr_rate
560 
561 
562 
563 
564 
565  !> Reads and counts the amount of theoretical weak rates
566  !!
567  !! Furthermore, this routine creates the rrate_weak array that is
568  !! merged into the total rate array rrate.
569  !!
570  !! \b Edited:
571  !! - 24.01.21, MR - copied it into this separate subroutine
572  !! .
575  use mergesort_module, only: rrate_sort
576  use benam_class, only: getcoefficients
578  implicit none
579 
580  integer :: twr_unit !< File ID of theoretical weak rate file
581  integer :: cnt !< Count variable for the amount of rates
582  integer :: i !< Loop variable
583 
584 
585  if ((iwformat.eq.1) .or. (iwformat.eq.2)) then
586  twr_unit= open_infile(weak_rates_file)
587 
588  !----- readweak(_logft) returns weak_rate(:) and number of weakrates
589  if ((iwformat.eq.1) .or. (iwformat.eq.2)) call readweak_logft(twr_unit,cnt)
590 
591  ! Set the correct number of rates
592  nweak = cnt
593 
594  !----- create rrate-type array of weak-rates, needed to merge them later
595  allocate(rrate_weak(cnt))
596  do i = 1,cnt
597  rrate_weak(i)%group = 1
598  rrate_weak(i)%parts = 0
599  rrate_weak(i)%parts(1:2) = weak_rate(i)%parts(1:2)
600  rrate_weak(i)%source = weak_rate(i)%source
601  rrate_weak(i)%is_reverse = .false.
602  rrate_weak(i)%is_resonant = .false.
603  rrate_weak(i)%is_weak = .true.
604  rrate_weak(i)%reac_src = rrs_twr
605  rrate_weak(i)%cached = -1
606  rrate_weak(i)%nu_frac = heating_frac
607  !----- Q-value of weakrates does not contain the electron rest mass
608  ! here it is added to get full Q-values in rrate. The weak_rate
609  ! Q-values are needed for the phase-space integral!
610  if (weak_rate(i)%is_ec) then
611  rrate_weak(i)%q_value = weak_rate(i)%q_value + unit%mass_e
612  rrate_weak(i)%reac_type = rrt_betp
613  n_ec=n_ec+1
614  else
615  n_o=n_o+1
616  rrate_weak(i)%q_value = weak_rate(i)%q_value - unit%mass_e
617  rrate_weak(i)%reac_type = rrt_betm
618  end if
619  rrate_weak(i)%param(1) = dble(i)
620  end do
621  !----- sort them(just to be sure)
622  call rrate_sort(cnt,rrate_weak)
623 
624  ! Close the file again
625  close(twr_unit)
626  ! get the correct coefficients
628  end if
629 
630  end subroutine
631 
632 
633 
634  !>
635  !! Reads weak reaction rates in log format
636  !!
637  !! This subroutine is called when parameter_class::iwformat was
638  !! set to 1. It assumes weak reaction rates that are
639  !! logarithmic. It will fill the global_class::weak_rate array
640  !! with rates that are later indicated by the label " ffn". An example
641  !! of the file that is read here is given by:
642  !! \file{
643  !! neg. daughter Sc45 z=21 n=24 a=45 Q= 0.7678
644  !! pos. daughter Ca45 z=20 n=25 a=45 Q= -0.7678
645  !! +++ Sc45 --> Ca45 +++ --- Ca45 --> Sc45 ---
646  !! t9 lrho uf lbeta+ lfte- lnu lbeta- lfte+ lnubar
647  !! 0.01 1.0 -0.003 -99.999 -99.999 -99.999 -7.302 -99.999 -0.746
648  !! 0.10 1.0 -0.058 -91.517 5.796 -1.577 -7.302 7.565 -0.746
649  !! 0.20 1.0 -0.134 -49.637 5.792 -1.266 -7.302 7.083 -0.746
650  !! ... }
651  !!
652  !! @remark Some rates in the file will replace rates from the reaclib, changing them there may not
653  !! have an effect as other rates are used then.
654  !!
655  !! @see parameter_class::temp_reload_exp_weak_rates, parameter_class::iwformat
656  !!
657  !! \b Edited:
658  !! - 12.01.14
659  !! - 11.03.22 (MR: extended routine for more general grids)
660  !! .
661  subroutine readweak_logft(sourcefile,cnt)
663  use global_class, only: isotope
664  use benam_class
665  use error_msg_class
666 
667  implicit none
668 
669  integer, intent(in) :: sourcefile !< file to read weak rates from
670  integer, intent(out) :: cnt !< total count of weak rates
671  !
672  real(r_kind) :: qfwd, qbwd !< q-values of forward and backward rates
673  real(r_kind) :: min_rho,max_rho,min_temp,max_temp
674  character*4,dimension(2) :: wnam
675  character*5,dimension(2) :: wparts
676  integer,dimension(2) :: parts_index
677  real(r_kind),dimension(:),allocatable :: beta_bwd,ec_ft,nu_loss,beta_fwd,mue_tmp
678  real(r_kind),dimension(:),allocatable :: pc_ft,anu_loss,t_grid,r_grid
679  integer,dimension(:),allocatable :: sort_keys
680  character(len=300) :: null
681  integer :: i,j,k,read_stat,alloc_stat,len_rate
682  integer :: count
683  logical :: cycle_loop
684 
685  info_entry("readweak_logft")
686 
687  k=0
688  walloc_loop: do
689  ! read weak rate from file
690  read(sourcefile,101, iostat = read_stat) wnam(1),qfwd
691  if (read_stat /= 0) exit
692  read(sourcefile,101) wnam(2),qbwd
693  read(sourcefile,*)
694  read(sourcefile,*)null
695  call convert(wnam,wparts)
696 
697  len_rate = 0
698  len_rate_loop: do
699  read(sourcefile,"(a)", iostat = read_stat)null
700  if (trim(adjustl(null)) .eq. "end") exit len_rate_loop
701  if (read_stat /= 0) exit len_rate_loop
702  len_rate = len_rate+1
703  end do len_rate_loop
704 
705  parts_index = 0
706  do j=1,2
707  parts_index(j) = benam(wparts(j))
708  if (parts_index(j) .eq. 0) then
709  cycle walloc_loop
710  end if
711  end do
712 
713  k=k+2
714  end do walloc_loop
715  nweak = k
716  allocate(weak_rate(nweak),stat=alloc_stat)
717  if ( alloc_stat /= 0) call raise_exception('Allocation of "weak_rate" failed',&
718  "readweak_logft",440001)
719  rewind(sourcefile)
720 
721  ! Count the grid length
722  k=0
723  wlength_loop: do
724  ! read weak rate from file
725  read(sourcefile,101, iostat = read_stat) wnam(1),qfwd
726  if (read_stat /= 0) exit
727  read(sourcefile,101) wnam(2),qbwd
728  read(sourcefile,*)
729  read(sourcefile,*)null
730  call convert(wnam,wparts)
731 
732  len_rate = 0
733  len_rate_loop2: do
734  read(sourcefile,"(a)", iostat = read_stat)null
735  if (trim(adjustl(null)) .eq. "end") exit len_rate_loop2
736  if (read_stat /= 0) exit len_rate_loop2
737  len_rate = len_rate+1
738  end do len_rate_loop2
739 
740  parts_index = 0
741  do j=1,2
742  parts_index(j) = benam(wparts(j))
743  if (parts_index(j) .eq. 0) then
744  cycle wlength_loop
745  end if
746  end do
747 
748  weak_rate(k+1)%n_points = len_rate
749  weak_rate(k+2)%n_points = len_rate
750 
751  k=k+2
752  end do wlength_loop
753  rewind(sourcefile)
754 
755 
756  k=1
757  wouter_loop: do
758  ! read weak rate from file
759  read(sourcefile,101, iostat = read_stat) wnam(1),qfwd
760  if (read_stat /= 0) exit
761  read(sourcefile,101) wnam(2),qbwd
762  read(sourcefile,*)
763  read(sourcefile,*)null
764  call convert(wnam,wparts)
765 
766  cycle_loop = .false.
767  parts_index = 0
768  do j=1,2
769  parts_index(j) = benam(wparts(j))
770  if (parts_index(j) .eq. 0) then
771  cycle_loop = .true.
772  end if
773  end do
774  if (cycle_loop) then
775  len_rate_loop3: do
776  read(sourcefile,"(a)", iostat = read_stat)null
777  if (trim(adjustl(null)) .eq. "end") exit len_rate_loop3
778  if (read_stat /= 0) exit len_rate_loop3
779  end do len_rate_loop3
780  cycle wouter_loop
781  end if
782 
783  ! Allocate everything.... a bit lengthy
784  if (allocated(beta_bwd)) then
785  if (size(beta_bwd) .ne. weak_rate(k)%n_points) then
786  deallocate(beta_bwd,ec_ft,nu_loss,beta_fwd,pc_ft,anu_loss,t_grid,r_grid,sort_keys,mue_tmp,stat=read_stat)
787  if (read_stat /= 0) call raise_exception("Deallocation of rate variables failed!",&
788  "readweak_logft",440002)
789 
790  allocate(beta_bwd(weak_rate(k)%n_points),ec_ft(weak_rate(k)%n_points),&
791  nu_loss(weak_rate(k)%n_points),beta_fwd(weak_rate(k)%n_points),&
792  pc_ft(weak_rate(k)%n_points),anu_loss(weak_rate(k)%n_points),&
793  t_grid(weak_rate(k)%n_points),r_grid(weak_rate(k)%n_points),&
794  sort_keys(weak_rate(k)%n_points),mue_tmp(weak_rate(k)%n_points),stat=read_stat)
795  if (read_stat /= 0) call raise_exception("Allocation of rate variables failed!",&
796  "readweak_logft",440001)
797  end if
798  else
799  allocate(beta_bwd(weak_rate(k)%n_points),ec_ft(weak_rate(k)%n_points),&
800  nu_loss(weak_rate(k)%n_points),beta_fwd(weak_rate(k)%n_points),&
801  pc_ft(weak_rate(k)%n_points),anu_loss(weak_rate(k)%n_points),&
802  t_grid(weak_rate(k)%n_points),r_grid(weak_rate(k)%n_points),&
803  sort_keys(weak_rate(k)%n_points),mue_tmp(weak_rate(k)%n_points),stat=read_stat)
804  if (read_stat /= 0) call raise_exception("Allocation of rate variables failed!",&
805  "readweak_logft",440001)
806  end if
807 
808  ! Get minimum and maximum grid values
809  min_temp=huge(min_temp)
810  max_temp=-1*huge(min_temp)
811  min_rho =huge(min_temp)
812  max_rho =-1*huge(min_temp)
813  ! Read everything
814  do i=1,weak_rate(k)%n_points
815  read(sourcefile,*)t_grid(i),r_grid(i),mue_tmp(i),beta_bwd(i),ec_ft(i),nu_loss(i),beta_fwd(i),pc_ft(i),anu_loss(i)
816  if (t_grid(i)<min_temp)min_temp=t_grid(i)
817  if (t_grid(i)>max_temp)max_temp=t_grid(i)
818  if (r_grid(i)<min_rho) min_rho =r_grid(i)
819  if (r_grid(i)>max_rho) max_rho =r_grid(i)
820  end do
821  read(sourcefile,'(a1)')null
822 
823 
824  ! Sort according to temperature
825  call bubblesort(1,weak_rate(k)%n_points,t_grid,sort_keys)
826  ! Count amount of temperature
827  count=1
828  do i=2,weak_rate(k)%n_points
829  if (t_grid(i) .ne. t_grid(i-1)) count = count + 1
830  end do
831  weak_rate(k)%n_temp_grid = count
832  allocate(weak_rate(k)%temp_grid(count))
833  ! Get the unique temperature points
834  weak_rate(k)%temp_grid(1) = t_grid(1)
835  count=1
836  do i=2,weak_rate(k)%n_points
837  if (t_grid(i) .ne. t_grid(i-1)) then
838  count = count + 1
839  weak_rate(k)%temp_grid(count) = t_grid(i)
840  end if
841  end do
842  ! Sort all values accordingly
843  call reorder(r_grid,sort_keys,weak_rate(k)%n_points)
844  call reorder(beta_bwd,sort_keys,weak_rate(k)%n_points)
845  call reorder(ec_ft,sort_keys,weak_rate(k)%n_points)
846  call reorder(nu_loss,sort_keys,weak_rate(k)%n_points)
847  call reorder(beta_fwd,sort_keys,weak_rate(k)%n_points)
848  call reorder(mue_tmp,sort_keys,weak_rate(k)%n_points)
849  call reorder(pc_ft,sort_keys,weak_rate(k)%n_points)
850  call reorder(anu_loss,sort_keys,weak_rate(k)%n_points)
851 
852  ! Now sort according to density
853  call bubblesort(1,weak_rate(k)%n_points,r_grid,sort_keys)
854  ! Count amount of density
855  count=1
856  do i=2,weak_rate(k)%n_points
857  if (r_grid(i) .ne. r_grid(i-1)) count = count + 1
858  end do
859  weak_rate(k)%n_rho_grid = count
860  allocate(weak_rate(k)%rho_grid(count))
861  ! Get unique densty values
862  weak_rate(k)%rho_grid(1) = r_grid(1)
863  count=1
864  do i=2,weak_rate(k)%n_points
865  if (r_grid(i) .ne. r_grid(i-1)) then
866  count = count + 1
867  weak_rate(k)%rho_grid(count) = r_grid(i)
868  end if
869  end do
870 
871  call reorder(t_grid,sort_keys,weak_rate(k)%n_points)
872  call reorder(beta_bwd,sort_keys,weak_rate(k)%n_points)
873  call reorder(ec_ft,sort_keys,weak_rate(k)%n_points)
874  call reorder(nu_loss,sort_keys,weak_rate(k)%n_points)
875  call reorder(beta_fwd,sort_keys,weak_rate(k)%n_points)
876  call reorder(mue_tmp,sort_keys,weak_rate(k)%n_points)
877  call reorder(pc_ft,sort_keys,weak_rate(k)%n_points)
878  call reorder(anu_loss,sort_keys,weak_rate(k)%n_points)
879 
880  ! Allocate the things in the weak rate type
881  allocate(weak_rate(k)%beta_rate(weak_rate(k)%n_temp_grid,weak_rate(k)%n_rho_grid),&
882  weak_rate(k)%mue_kin(weak_rate(k)%n_temp_grid,weak_rate(k)%n_rho_grid),&
883  weak_rate(k)%ft_rate(weak_rate(k)%n_temp_grid,weak_rate(k)%n_rho_grid),&
884  weak_rate(k)%nu_loss(weak_rate(k)%n_temp_grid,weak_rate(k)%n_rho_grid),stat=read_stat )
885  if (read_stat /= 0) call raise_exception("Allocation of rate variables failed!",&
886  "readweak_logft",440001)
887 
888  count=1
889 
890  if (weak_rate(k)%n_rho_grid*weak_rate(k)%n_temp_grid .ne. weak_rate(k)%n_points) then
891  call raise_exception("The weak rate grid was not a regular grid! Check weak rate:"//&
892  isotope(parts_index(1))%name//" ---> "//isotope(parts_index(2))%name//&
893  new_line('A')//"Number of rho gridpoints : "//int_to_str(weak_rate(k)%n_rho_grid)//&
894  new_line('A')//"Number of T gridpoints : "//int_to_str(weak_rate(k)%n_temp_grid)//&
895  new_line('A')//"Total number of gridpoints: "//int_to_str(weak_rate(k)%n_points),&
896  "readweak_logft",440003)
897  end if
898 
899  do j=1, weak_rate(k)%n_rho_grid
900  do i=1, weak_rate(k)%n_temp_grid
901  weak_rate(k)%beta_rate(i,j) = beta_fwd(count)
902  weak_rate(k)%mue_kin(i,j) = mue_tmp(count)
903  weak_rate(k)%ft_rate(i,j) = pc_ft(count)
904  weak_rate(k)%nu_loss(i,j) = anu_loss(count)
905  count = count + 1
906  end do
907  end do
908  weak_rate(k)%parts(1) = parts_index(2)
909  weak_rate(k)%parts(2) = parts_index(1)
910  weak_rate(k)%q_value = qfwd
911  weak_rate(k)%source = ' ffn'
912  weak_rate(k)%min_temp = min_temp
913  weak_rate(k)%max_temp = max_temp
914  weak_rate(k)%min_rho = min_rho
915  weak_rate(k)%max_rho = max_rho
916  weak_rate(k)%is_ec = .false.
917 
918  k=k+1
919  ! Assign same grid length
920  weak_rate(k)%n_temp_grid = weak_rate(k-1)%n_temp_grid
921  weak_rate(k)%n_rho_grid = weak_rate(k-1)%n_rho_grid
922  ! And the same grid
923  allocate(weak_rate(k)%temp_grid(weak_rate(k)%n_temp_grid ))
924  allocate(weak_rate(k)%rho_grid(weak_rate(k)%n_rho_grid ))
925  weak_rate(k)%temp_grid = weak_rate(k-1)%temp_grid
926  weak_rate(k)%rho_grid = weak_rate(k-1)%rho_grid
927 
928  ! Allocate the things in the weak rate type
929  allocate(weak_rate(k)%beta_rate(weak_rate(k)%n_temp_grid,weak_rate(k)%n_rho_grid),&
930  weak_rate(k)%mue_kin(weak_rate(k)%n_temp_grid,weak_rate(k)%n_rho_grid),&
931  weak_rate(k)%ft_rate(weak_rate(k)%n_temp_grid,weak_rate(k)%n_rho_grid),&
932  weak_rate(k)%nu_loss(weak_rate(k)%n_temp_grid,weak_rate(k)%n_rho_grid),stat=read_stat )
933  if (read_stat /= 0) call raise_exception("Allocation of rate variables failed!",&
934  "readweak_logft",440001)
935 
936  count=1
937  do j=1, weak_rate(k)%n_rho_grid
938  do i=1, weak_rate(k)%n_temp_grid
939  weak_rate(k)%beta_rate(i,j) = beta_bwd(count)
940  weak_rate(k)%mue_kin(i,j) = mue_tmp(count)
941  weak_rate(k)%ft_rate(i,j) = ec_ft(count)
942  weak_rate(k)%nu_loss(i,j) = nu_loss(count)
943  count = count + 1
944  end do
945  end do
946 
947  weak_rate(k)%parts(1) = parts_index(1)
948  weak_rate(k)%parts(2) = parts_index(2)
949  weak_rate(k)%q_value = qbwd
950  weak_rate(k)%source = ' ffn'
951  weak_rate(k)%min_temp = min_temp
952  weak_rate(k)%max_temp = max_temp
953  weak_rate(k)%min_rho = min_rho
954  weak_rate(k)%max_rho = max_rho
955  weak_rate(k)%is_ec = .true.
956  cnt=k
957  k=k+1
958 
959  end do wouter_loop
960  call sort(cnt)
961 
962  info_exit("readweak_logft")
963 
964  101 format(t16,a4,t38,f8.4)
965 
966  end subroutine readweak_logft
967 
968 
969 
970 
971 
972  !>
973  !! Set wk_index for given T, @f$\rho@f$ and @f$Y_e@f$
974  !! The index is written into module variable \ref wk_index
975  !!
976  !! After the subroutine has been called the correct indices for a two
977  !! dimensional interpolation are stored in \ref wk_index.
978  !!
979  !! @see weak_inter, readweak_logft, parameter_class::iwinterp, inter_module::get_indice_2D
980  !!
981  !! \b Edited:
982  !! - MR : 19.01.2021 - Removed hard coded temperatures
983  !! - MR : 11.03.2022 - Rates are now on two dimensional grid, rewrote this routine
984  !! - MR : 06.07.2022 - Moved things to inter_module, now it is only an interface
985  !! .
986  subroutine weak_index (ltemp, rho, Ye, wrt)
987  use inter_module, only:get_indice_2d
988  implicit none
989  real(r_kind),intent(in) :: ltemp !< Temperature [GK]
990  real(r_kind),intent(in) :: rho !< Density [g/ccm]
991  real(r_kind),intent(in) :: ye !< Electron fraction
992  type(weakrate_type),intent(in) :: wrt !< Input weak rate type
993  real(r_kind) :: lrho !< Logarithm of the \f$ \rho \cdot Y_e \f$
994 
995  lrho = dlog10(rho*ye)
996  call get_indice_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,&
997  wrt%n_temp_grid,wrt%n_rho_grid,wk_index)
998 
999  end subroutine weak_index
1000 
1001 
1002  !> Interpolation interface.
1003  !!
1004  !! This function interpolates the weak rates either bilinear or bicubic
1005  !!
1006  !! @author: M. Reichert
1007  !! @date: 14.03.22
1008  !!
1009  !! @warning The bicubic interpolation fails at values where -99 is neighboring.
1010  !! There, it produces artifacts. For mue, it is, however, okay.
1011  !!
1012  !! \b Edited:
1013  !! - MR : 06.07.2022 - Moved things to interpolation module
1014  !! .
1015  function weak_inter(rate,ltemp,lrho,wrt,force_cubic) result (wr)
1016  use parameter_class, only: iwinterp
1019  implicit none
1020  real(r_kind),intent(in) :: lrho !< Log(\f$ \rho \cdot Y_e \f$)
1021  real(r_kind),intent(in) :: ltemp !< Temperature [GK]
1022  logical,intent(in),optional :: force_cubic !< Whether or not a cubic interpolation should be applied
1023  integer :: rate !< Index for rate. 1: ft_rate, 2: beta_rate, 3: mue, 4: nu_loss
1024  type(weakrate_type),intent(in) :: wrt !< Input weak rate type
1025  real(r_kind) :: wr !< Weak reaction rate, interpolated at the desired temp and dens
1026 
1027  ! 0: bilinear interpolation, 1: bicubic interpolation
1028  if (.not. present(force_cubic)) then
1029  select case(iwinterp)
1030  case(0)
1031  if (rate .eq. ft_ident) then
1032  wr = lininter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%ft_rate,&
1033  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1034  elseif (rate .eq. beta_ident) then
1035  wr = lininter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%beta_rate,&
1036  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1037  elseif (rate .eq. mue_ident) then
1038  wr = lininter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%mue_kin,&
1039  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1040  elseif (rate .eq. nu_loss_ident) then
1041  wr = lininter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%nu_loss,&
1042  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1043  else
1044  call raise_exception("Unknown array to interpolate, got "//int_to_str(rate),&
1045  "weak_inter",440009)
1046  end if
1047  case(1)
1048  if (rate .eq. ft_ident) then
1049  wr = cubinter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%ft_rate,&
1050  wrt%dft_dT,wrt%dft_dR,wrt%dft_dT_dR,&
1051  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1052  elseif (rate .eq. beta_ident) then
1053  wr = cubinter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%beta_rate,&
1054  wrt%dbeta_dT,wrt%dbeta_dR,wrt%dbeta_dT_dR,&
1055  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1056  elseif (rate .eq. mue_ident) then
1057  wr = cubinter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%mue_kin,&
1058  wrt%dmue_kin_dT,wrt%dmue_kin_dR,wrt%dmue_kin_dT_dR,&
1059  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1060  elseif (rate .eq. nu_loss_ident) then
1061  call raise_exception("Cubic interpolation not implemented for nu_loss",&
1062  "weak_inter") ! TODO implement error code
1063  end if
1064  case default
1065  call raise_exception("Unknown iwinterp type, got "//int_to_str(iwinterp),&
1066  "weak_inter",440004)
1067  end select
1068  else
1069  if (rate .eq. ft_ident) then
1070  wr = cubinter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%ft_rate,&
1071  wrt%dft_dT,wrt%dft_dR,wrt%dft_dT_dR,&
1072  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1073  elseif (rate .eq. beta_ident) then
1074  wr = cubinter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%beta_rate,&
1075  wrt%dbeta_dT,wrt%dbeta_dR,wrt%dbeta_dT_dR,&
1076  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1077  elseif (rate .eq. mue_ident) then
1078  wr = cubinter_2d(ltemp,lrho,wrt%temp_grid,wrt%rho_grid,wrt%mue_kin,&
1079  wrt%dmue_kin_dT,wrt%dmue_kin_dR,wrt%dmue_kin_dT_dR,&
1080  wrt%n_temp_grid,wrt%n_rho_grid,wk_index,2)
1081  elseif (rate .eq. nu_loss_ident) then
1082  call raise_exception("Cubic interpolation not implemented for nu_loss",&
1083  "weak_inter") ! TODO implement error code
1084  end if
1085  end if
1086 
1087  ! Values are in logarithmic scale, convert back
1088  if (wr .lt. -30) then
1089  wr = 0.d0
1090  else
1091  wr = 1.d1**(wr)
1092  end if
1093 
1094  ! Check that it is not NaN
1095  if (wr .ne. wr) call raise_exception("Value got NaN in interpolation.",&
1096  "weak_inter")
1097 
1098  return
1099  end function weak_inter
1100 
1101 
1102  !>
1103  !! This routine is used to replace theoretical weak rates with experimental ones
1104  !! it's called when T9 < parameter_class::temp_reload_exp_weak_rates (default 1d-2)
1105  !!
1106  !! @remark Some rates will replace rates from the reaclib, changing them there may not
1107  !! have an effect for low temperatures as other rates are used then.
1108  !!
1109  !! @see parameter_class::temp_reload_exp_weak_rates, parameter_class::iwformat
1110  !! weak_index, weak_inter, temp_grid_weak
1111  !!
1112  !! \b Edited:
1113  !! - 27.01.21, M.R.
1114  !! - 23.03.23, M.R.
1115  !! .
1117 
1118  use parameter_class
1119  use global_class
1120  use benam_class
1121  use format_class
1122  use mergesort_module
1123 
1124  implicit none
1125  integer :: i, j, k, elements_still_to_replace,elements_still_to_remove
1126  logical :: replaced
1127 
1128  info_entry("reload_exp_weak_rates")
1129 
1130  elements_still_to_replace = common_weak_rates
1131  elements_still_to_remove = only_theo_weak_rates
1132 
1133  i = 1
1134  do while ((elements_still_to_replace .gt. 0).or.(elements_still_to_remove .gt. 0))
1135  if (rrate(i)%reac_src .eq. rrs_twr) then
1136  replaced = .false.
1137  do j = 1, common_weak_rates
1138  if ((rrate(i)%parts(1) .eq. rrate_weak_exp(j)%parts(1)) .and. &
1139  (rrate(i)%parts(2) .eq. rrate_weak_exp(j)%parts(2))) then
1140 
1141  rrate(i)%source = rrate_weak_exp(j)%source
1142  rrate(i)%q_value = rrate_weak_exp(j)%q_value
1143  rrate(i)%param = rrate_weak_exp(j)%param
1144  rrate(i)%reac_src = rrate_weak_exp(j)%reac_src
1145  rrate(i)%is_weak = .true.
1146  rrate(i)%reac_type = rrate_weak_exp(j)%reac_type
1147  rrate(i)%is_resonant = rrate_weak_exp(j)%is_resonant
1148  rrate(i)%is_reverse = rrate_weak_exp(j)%is_reverse
1149  rrate(i)%is_const = rrate_weak_exp(j)%is_const
1150  rrate(i)%nu_frac = rrate_weak_exp(j)%nu_frac
1151  rrate(i)%ch_amount(1) = -1.d0
1152  do k=2,6
1153  if (rrate(i)%parts(k).ne.0) rrate(i)%ch_amount(k) = 1.d0
1154  end do
1155  elements_still_to_replace = elements_still_to_replace - 1
1156  replaced = .true.
1157  exit
1158  end if
1159  end do
1160  if (.not.replaced) then
1161  ! Put empty rate in order to not shift indices
1162  rrate(i)%is_reverse = .false.
1163  rrate(i)%is_resonant = .false.
1164  rrate(i)%is_weak = .true.
1165  rrate(i)%reac_type = rrt_o
1166  rrate(i)%reac_src = rrs_reacl
1167  rrate(i)%ch_amount(:)= 0.d0
1168  rrate(i)%param(:) = 0
1169  rrate(i)%param(1) = -99
1170  rrate(i)%nu_frac = 0
1171  !MR: changed this to nreac -1 to stay in array bounds
1172  ! The following should not happen as it shifts indices that
1173  ! are needed by other rates
1174  ! (test with -check bounds compiler flag)
1175  ! do j = i, nreac-1
1176  ! rrate(j) = rrate(j+1)
1177  ! end do
1178  ! i = i-1
1179  elements_still_to_remove = elements_still_to_remove - 1
1180  end if
1181  end if
1182  i = i+1
1183  if (i .gt. nreac) exit
1184  end do
1185 
1186  ! As empty rates are introduced now, this is not necessary.
1187  ! nreac = nreac - only_theo_weak_rates
1188  deallocate(rrate_weak_exp)
1189 
1190  if (elements_still_to_replace .gt. 0) call raise_exception("Couldn't replace all weak rates!",&
1191  "reload_exp_weak_rates",&
1192  440005)
1193  if (elements_still_to_replace .lt. 0) call raise_exception("Replaced too many rates!",&
1194  "reload_exp_weak_rates",&
1195  440006)
1196  if (elements_still_to_remove .gt. 0) call raise_exception("Couldn't remove all weak rates!",&
1197  "reload_exp_weak_rates",&
1198  440007)
1199  if (elements_still_to_remove .lt. 0) call raise_exception("Removed too many rates!",&
1200  "reload_exp_weak_rates",&
1201  440008)
1202  info_exit("reload_exp_weak_rates")
1203 
1204  return
1205 
1206  end subroutine reload_exp_weak_rates
1207 
1208 
1209  !< Debug routine to output n <-> p reactions
1210  !!
1211  !! This routine creates the file "np_twr.dat", containing a variety of
1212  !! interpolated <ft> values. This can be useful to test the implemented
1213  !! interpolations.
1214  !!
1215  !! @author: M. Reichert
1216  !! @date: 05.07.22
1217  subroutine output_n_p
1218  use global_class, only: ineu,ipro
1220  implicit none
1221  integer :: i,j !< Loop variable
1222  integer :: ind_n_p !< Index of the rate n -> p
1223  integer :: ind_p_n !< Index of the rate p -> n
1224  integer :: funit !< Unit for weak rates
1225  real(r_kind) :: temp_min,temp_max,temp_incr !< Minimum, Maximum, and increment of temperature for output
1226  real(r_kind) :: rho_min ,rho_max ,rho_incr,rholog !< Minimum, Maximum, and increment of electron density for output
1227  real(r_kind) :: temp_tmp,rho_tmp,ye_tmp
1228  real(r_kind) :: rat_pc,rat_ec,rat_bm,rat_bp
1229 
1230  if (verbose_level .ge. 2) then
1231  temp_min = 0.0; temp_max = 101; temp_incr = 0.01
1232  rho_min = 0.5; rho_max = 10.5; rho_incr = 0.25
1233  ind_n_p = -1
1234  ind_p_n = -1
1235  do i=1, nweak
1236  if ((weak_rate(i)%parts(1) .eq. ineu) .and. (weak_rate(i)%parts(2) .eq. ipro)) then
1237  ind_n_p= i
1238  end if
1239  if ((weak_rate(i)%parts(2) .eq. ineu) .and. (weak_rate(i)%parts(1) .eq. ipro)) then
1240  ind_p_n= i
1241  end if
1242  end do
1243 
1244  ! Only continue if rates are included
1245  if ((ind_n_p .eq. -1) .or. (ind_p_n .eq. -1)) return
1246  ! Open the file for debugging
1247  funit= open_outfile("np_twr.dat")
1248  write(funit,*) "#Temp [GK] rho*ye bp ec bm pc wk11 wk12 wk21 wk22"
1249  ye_tmp = 1
1250  temp_tmp = temp_min
1251  do i=1, int((temp_max-temp_min)/temp_incr)
1252  rho_tmp = rho_min
1253  do j=1, int((rho_max-rho_min)/rho_incr)
1254  rholog = 10**rho_tmp
1255 
1256  call weak_index (temp_tmp, rholog, ye_tmp, weak_rate(ind_n_p))
1257  rat_pc= weak_inter(ft_ident,temp_tmp,rho_tmp,weak_rate(ind_n_p))
1258  rat_ec= weak_inter(ft_ident,temp_tmp,rho_tmp,weak_rate(ind_p_n))
1259  rat_bm= weak_inter(beta_ident,temp_tmp,rho_tmp,weak_rate(ind_n_p))
1260  rat_bp= weak_inter(beta_ident,temp_tmp,rho_tmp,weak_rate(ind_p_n))
1261 
1262  write(funit,"((6es12.5,4I4))") temp_tmp,rho_tmp,rat_bp,rat_ec,rat_bm,rat_pc,wk_index(1,1),wk_index(1,2),wk_index(2,1),wk_index(2,2)
1263  rho_tmp = rho_tmp+rho_incr
1264  end do
1265  temp_tmp = temp_tmp+temp_incr
1266  end do
1267  call close_io_file(funit, "np_twr.dat")
1268  end if
1269  end subroutine output_n_p
1270 
1271 
1272  !----------------------------Auxiliary helper functions---------------------!
1273  !---------------------------------------------------------------------------!
1274 
1275 
1276 
1277 
1278  !> Sorts the entries in weak_rate in increasing order of the decaying nuclide
1279  !!
1280  subroutine sort(cnt)
1281 
1282  use error_msg_class
1283  implicit none
1284  integer, intent(in) :: cnt
1285  integer :: min_index, alloc_stat
1286  integer :: i,j,k
1287  type(weakrate_type),dimension(:),allocatable :: weak_temp
1288 
1289  allocate(weak_temp(nweak),stat=alloc_stat)
1290  if(alloc_stat /= 0) call raise_exception('Allocation of "weak_temp" failed',&
1291  "sort",440001)
1292 
1293  do i = 1,cnt
1294  do k=1,cnt
1295  if(weak_rate(k)%parts(1).gt.0) min_index = k
1296  end do
1297  do j=1,cnt
1298  if ((weak_rate(j)%parts(1).gt.0).and. &
1299  (weak_rate(j)%parts(1).eq.weak_rate(min_index)%parts(1)).and. &
1300  (weak_rate(j)%parts(2).lt.weak_rate(min_index)%parts(2))) then
1301  min_index = j
1302  else if((weak_rate(j)%parts(1).gt.0).and. &
1303  (weak_rate(j)%parts(1).lt.weak_rate(min_index)%parts(1))) then
1304  min_index = j
1305  end if
1306  end do
1307  weak_temp(i) = weak_rate(min_index)
1308  weak_rate(min_index)%parts(1) = -1
1309  end do
1310 
1311  weak_rate = weak_temp
1312  deallocate(weak_temp)
1313 
1314  end subroutine sort
1315 
1316 
1317 end module tw_rate_module
parameter_class::iwformat
integer iwformat
defines format of the weak rates (0 = tabulated, 1 = log<ft>)
Definition: parameter_class.f90:81
tw_rate_module::readweak_logft
subroutine, private readweak_logft(sourcefile, cnt)
Reads weak reaction rates in log format.
Definition: tw_rate_module.f90:662
tw_rate_module::rrate_weak
type(reactionrate_type), dimension(:), allocatable, private rrate_weak
Reaction rate representative in global_class::rrate.
Definition: tw_rate_module.f90:60
parameter_class::use_prepared_network
logical use_prepared_network
Use a prepared folder with all necessary data in binary format.
Definition: parameter_class.f90:94
global_class::ipro
integer, public ipro
index of alphas, neutrons and protons
Definition: global_class.f90:94
global_class::reactionrate_type
reaction rate type
Definition: global_class.f90:44
global_class::rrate
type(reactionrate_type), dimension(:), allocatable, public rrate
array containing all reaction rates used in the network
Definition: global_class.f90:65
inter_module
Module inter_module with interpolation routines.
Definition: inter_module.f90:13
global_class::common_weak_rates
integer common_weak_rates
Counter for rates that are included in Reaclib and theoretical weak rates.
Definition: global_class.f90:101
tw_rate_module::weak_rate
type(weakrate_type), dimension(:), allocatable, public weak_rate
array containing the weak reactions
Definition: tw_rate_module.f90:56
tw_rate_module::read_binary_weak_reaction_data
subroutine read_binary_weak_reaction_data(path)
Read the theoretical weak rates from a unformatted binary file.
Definition: tw_rate_module.f90:260
tw_rate_module::wk_index
integer, dimension(2, 2), private wk_index
Multi-index for the weak rates.
Definition: tw_rate_module.f90:61
rrs_reacl
#define rrs_reacl
Definition: macros.h:49
error_msg_class
Error handling routines.
Definition: error_msg_class.f90:16
benam_class::benam
integer function, public benam(name)
Returns the index number of isotope 'name'.
Definition: benam_class.f90:251
error_msg_class::int_to_str
character(:) function, allocatable, public int_to_str(num)
Converts a given integer to a string.
Definition: error_msg_class.f90:224
inter_module::get_indice_2d
subroutine, public get_indice_2d(xval, yval, x, y, x_dim, y_dim, indices)
Get indices of the grid for given x- and y- values.
Definition: inter_module.f90:587
error_msg_class::raise_exception
subroutine, public raise_exception(msg, sub, error_code)
Raise a exception with a given error message.
Definition: error_msg_class.f90:245
mergesort_module::rrate_ms
subroutine, public rrate_ms(x, xs, y, ys, r, ptz, rate_out)
Merges two tables of rates (of type global_class::reactionrate_type).
Definition: mergesort_module.f90:227
global_class::rrate_weak_exp
type(reactionrate_type), dimension(:), allocatable, public rrate_weak_exp
array saving the exp. weak rates from reaclib that are replaced by theo weak rates
Definition: global_class.f90:66
tw_rate_module::weakrate_type
data fields for weak rates given in Langanke&Martinez-Pinedo 2001
Definition: tw_rate_module.f90:29
parameter_class::use_timmes_mue
logical use_timmes_mue
Use electron chemical potentials from timmes EOS for theoretical weak rates.
Definition: parameter_class.f90:96
tw_rate_module::mue_ident
integer, parameter, private mue_ident
Identifier for chemical potential.
Definition: tw_rate_module.f90:63
tw_rate_module::reload_exp_weak_rates
subroutine, public reload_exp_weak_rates()
This routine is used to replace theoretical weak rates with experimental ones it's called when T9 < p...
Definition: tw_rate_module.f90:1117
parameter_class::max_fname_len
integer, parameter, public max_fname_len
maximum length of filenames
Definition: parameter_class.f90:58
global_class::ineu
integer, public ineu
Definition: global_class.f90:94
tw_rate_module::write_reac_verbose_out
subroutine, private write_reac_verbose_out()
Write the amount of individual reactions to the out.
Definition: tw_rate_module.f90:181
global_class::isotope
type(isotope_type), dimension(:), allocatable, public isotope
all nuclides used in the network
Definition: global_class.f90:34
error_msg_class::write_data_to_std_out
subroutine, public write_data_to_std_out(str_msg, value_str, unit)
Write data to the standard output (usually OUT)
Definition: error_msg_class.f90:122
parameter_class::iwinterp
integer iwinterp
defines the interpolation for the weak rates (0 = bilinear, 1 = bicubic)
Definition: parameter_class.f90:82
tw_rate_module::mue
real(r_kind), public mue
chemical potential of the electron
Definition: tw_rate_module.f90:62
rrt_betp
#define rrt_betp
Definition: macros.h:60
tw_rate_module::n_o
integer, private n_o
individual reaction types
Definition: tw_rate_module.f90:68
tw_rate_module::weak
logical, public weak
switch for weak rates
Definition: tw_rate_module.f90:58
mergesort_module::reorder
subroutine, public reorder(arr1, arr2, length)
Takes an array and an array with indices to reorder the first array.
Definition: mergesort_module.f90:901
tw_rate_module::nu_loss_ident
integer, parameter, private nu_loss_ident
Identifier for the neutrino loss.
Definition: tw_rate_module.f90:66
global_class::only_theo_weak_rates
integer only_theo_weak_rates
Counter for rates that are not included in Reaclib, but in theoretical weak rates.
Definition: global_class.f90:102
mergesort_module::rrate_sort
subroutine, public rrate_sort(num, rate_array)
Sorts chapter one of the rate array.
Definition: mergesort_module.f90:676
rrs_twr
#define rrs_twr
Definition: macros.h:52
tw_rate_module::weak_binary_name
character(len= *), parameter, private weak_binary_name
Filename of binary file to save weak rates.
Definition: tw_rate_module.f90:69
effphase_class::effphase
subroutine, public effphase(temp, chem, qec, phaseint)
Definition: effphase_class.f90:37
effphase_class
Calculate the effective phase space integral needed for the log(ft) weak rates.
Definition: effphase_class.f90:18
parameter_class::unit
type(unit_type), public unit
constants and unit conversion factors
Definition: parameter_class.f90:54
parameter_class::heating_frac
real(r_kind) heating_frac
use this fraction of nuclear-generated energy for heating
Definition: parameter_class.f90:123
file_handling_class
Provide some basic file-handling routines.
Definition: file_handling_class.f90:18
tw_rate_module::ft_ident
integer, parameter, private ft_ident
Identifier for forward rate.
Definition: tw_rate_module.f90:65
parameter_class::weak_rates_file
character(max_fname_len) weak_rates_file
weak rates library (twr.dat)
Definition: parameter_class.f90:169
tw_rate_module::initialize_cubic_interp
subroutine initialize_cubic_interp
Calculate derivatives of weak reactions.
Definition: tw_rate_module.f90:122
tw_rate_module::beta_ident
integer, parameter, private beta_ident
Identifier for beta rate.
Definition: tw_rate_module.f90:64
r_kind
#define r_kind
Definition: macros.h:46
tw_rate_module::n_ec
integer, private n_ec
Definition: tw_rate_module.f90:68
tw_rate_module::weak_index
subroutine, public weak_index(ltemp, rho, Ye, wrt)
Set wk_index for given T, and The index is written into module variable wk_index.
Definition: tw_rate_module.f90:987
tw_rate_module::read_theoretical_weak_rates
subroutine, private read_theoretical_weak_rates()
Reads and counts the amount of theoretical weak rates.
Definition: tw_rate_module.f90:574
inter_module::cubinter_2d
real(r_kind) function, public cubinter_2d(xin, yin, x, y, f, dfx, dfy, dfxy, x_dim, y_dim, indice, extrapolation)
Cubic interpolate on 2-Dimensional grid.
Definition: inter_module.f90:795
tw_rate_module::nweak
integer, private nweak
number of weak reactions taken from Langanke&Martinez-pinedo
Definition: tw_rate_module.f90:59
rrt_betm
#define rrt_betm
Definition: macros.h:59
rrt_o
#define rrt_o
Definition: macros.h:81
tw_rate_module::init_theoretical_weak_rates
subroutine, public init_theoretical_weak_rates()
Initialize theoretical weak rates.
Definition: tw_rate_module.f90:91
file_handling_class::open_infile
integer function, public open_infile(file_name)
Same for reading (input file)
Definition: file_handling_class.f90:126
file_handling_class::open_outfile
integer function, public open_outfile(file_name)
Shorthand for opening a new file for writing (output file)
Definition: file_handling_class.f90:108
tw_rate_module::output_n_p
subroutine output_n_p
Definition: tw_rate_module.f90:1218
benam_class::convert
subroutine, public convert(wnam, rnam)
Converts isotope names of weak-table format to the ones in reaclib.
Definition: benam_class.f90:223
global_class
Contains types and objects shared between multiple modules.
Definition: global_class.f90:19
global_class::nreac
integer, public nreac
total number of reactions
Definition: global_class.f90:98
tw_rate_module::merge_theoretical_weak_rates
subroutine merge_theoretical_weak_rates(rrate_array, rrate_length)
Merge theoretical weak rates into larger rate array.
Definition: tw_rate_module.f90:209
inter_module::lininter_2d
real(r_kind) function, public lininter_2d(xin, yin, x, y, f, x_dim, y_dim, indice, extrapolation)
Interpolate linearly on 2 Dimensional grid.
Definition: inter_module.f90:699
file_handling_class::close_io_file
subroutine, public close_io_file(unit_no, file_name)
Close an external file.
Definition: file_handling_class.f90:144
tw_rate_module
This module contains everything for the theoretical weak rates that are added into the rate array.
Definition: tw_rate_module.f90:23
file_handling_class::open_unformatted_outfile
integer function, public open_unformatted_outfile(file_name)
Shorthand for opening a new unformatted file for writing (output file)
Definition: file_handling_class.f90:74
format_class
Define custom format statements used to read in major data files.
Definition: format_class.f90:16
tw_rate_module::output_binary_weak_reaction_data
subroutine, public output_binary_weak_reaction_data(path)
Save the theoretical weak rates to a unformatted binary file.
Definition: tw_rate_module.f90:391
file_handling_class::open_unformatted_infile
integer function open_unformatted_infile(file_name)
Open an unformatted file for reading.
Definition: file_handling_class.f90:89
mergesort_module::bubblesort
subroutine, public bubblesort(mode, length, arr1, arr2)
Bubblesort of array.
Definition: mergesort_module.f90:724
mergesort_module
Module mergesort_module for merging arrays of rates.
Definition: mergesort_module.f90:16
inter_module::calc_derivative_2d
subroutine, public calc_derivative_2d(f, x, y, dfx, dfy, dfxy, x_dim, y_dim)
Calculate derivatives at all points in a given grid.
Definition: inter_module.f90:623
tw_rate_module::sort
subroutine, private sort(cnt)
Sorts the entries in weak_rate in increasing order of the decaying nuclide.
Definition: tw_rate_module.f90:1281
parameter_class::prepared_network_path
character(max_fname_len) prepared_network_path
Prepared network folder.
Definition: parameter_class.f90:198
tw_rate_module::weak_inter
real(r_kind) function, public weak_inter(rate, ltemp, lrho, wrt, force_cubic)
Interpolation interface.
Definition: tw_rate_module.f90:1016
parameter_class
Contains all runtime parameters as well as phys and math constants.
Definition: parameter_class.f90:24
tw_rate_module::calculate_twr_rate
subroutine, public calculate_twr_rate(rrate, temp, rho, Ye, rat_calc, nuloss)
Calculate the theoretical weak rate.
Definition: tw_rate_module.f90:485
benam_class::getcoefficients
subroutine, public getcoefficients(rate_array, length_rate_array)
Returns the 1/n! factor where n is the number of equal isotopes entering a reaction....
Definition: benam_class.f90:307
benam_class
Subroutines needed to initialise the network.
Definition: benam_class.f90:11