!> Interface for 1D interpolation routines.
!!
!! This routine is a wrapper for the 1D interpolation routines
!! lininter, cubinter, akimainter, makimainter, and pchipinter.
!! The interpolation type is controlled by the optional argument
!! itype. If itype is absent, \ref interp_mode is used.
!! The optional argument flin allows to control the return value:
!! - if flin is absent: return exp(log(y)) = y;
!! - if flin is present: return log(y).
!!
!! @author M. Reichert
!! @date 01.05.2023


!>
!! Cubic interpolation in log-log space. Here, it is assumed that
!!
!! the x and y arrays are given in the form of {x_i, log(y_i)},
!! but before interpolating the x coordinate, it is transformed
!! to a log space: {log(x_i), log(y_i)}.
!! An optional argument flin allows to control the return value:
!!  - if flin is absent: return exp(log(y)) = y;
!!  - if flin is present: return log(y).
!!
!! \b Edited:
!!     - 14.01.14
!! .


!> PCHIP interpolation in lin-log space.
!!
!! The Piecewise Cubic Hermite Interpolating Polynomial (PCHIP)
!! interpolation is a method for interpolating data points where
!! every section between points is monoton. The interpolation
!! avoids overshoots and undershoots and is close to the linear
!! interpolation, but having the first derivative continuous.
!!
!! @see F. N. Fritsch and R. E. Carlson, Monotone Piecewise Cubic
!!      Interpolation, SIAM Journal on Numerical Analysis, 17(2),
!!      1980, pp. 238-246.
!!      [Steffen 1990](https://ui.adsabs.harvard.edu/abs/1990A%26A...239..443S/abstract)
!! @author: M. Reichert
!! @date: 01.05.2023


!> Calculate derivatives at all points in a given grid.
!!
!! These derivatives are necessary for the cubic interpolation.
!! The subroutine returns the derivative df/dx, df/dy, and ddf/dxdy.
!! They are second order accurate, i.e.,
!! \f[ df/dx = \frac{h_1^2 f(x+h_2) + (h_2^2-h_1^2)f(x)-h_2^2 f(x-h_1) }{h_1 h_2 (h_1+h_2)} \f]
!!
!! @author: M. Reichert
!! @date 06.07.22


!> Interpolate linearly on 2 Dimensional grid
!!
!! Bilinear interpolation
!!
!! @see weak_inter
!!
!! @author: M. Reichert
!! @date: 06.07.22
!! .


!> Cubic interpolate on 2-Dimensional grid
!!
!! This interpolation is a bicubic interpolation. For values outside the grid,
!! either a constant extrapolation is performed or an error is raised.
!!
!! @see weak_inter_bilinear, weak_inter, readweak_logft
!!
!! @author: Moritz Reichert
!! @date:  14.03.22
!!
!! @see [Bicubic interpolation](https://en.wikipedia.org/wiki/Bicubic_interpolation)
!! .


!>
!! The inverse of the 1D interpolation function.
!!
!! Interface to the inverse interpolation functions using either
!! Newton-Raphson or Brent's method.
!!
!! @author M. Reichert
!! @date 16.10.2024
!!
!! @see timestep_module::restrict_timestep
!!


!>
!! The inverse of the 1D interpolation function.
!!
!! Finds the inverse of interp1d and returns the value of x.
!! This is done by using a Newton-Raphson method.
!!
!! @note The result depends on xb, because x_i does not necessarily have
!!       to be monotonic. The result should be the closest value to xb.
!!       This is however not always the case in which brents method might be
!!       more suitable.
!!
!! @author M. Reichert
!!
!! \b Edited:
!!        - 30.01.23
!! .


!>
!! The inverse of the 1D interpolation function.
!!
!! Finds the inverse of interp1d and returns the value of x using Brent's method,
!! a hybrid root-finding algorithm that combines the robustness of the bisection method
!! with the speed of inverse quadratic interpolation and the secant method.
!! Brent's method ensures that the root is bracketed at every iteration,
!! providing a reliable and efficient way to converge on the solution.
!! For more details, see the
!! [wikipedia](https://en.wikipedia.org/wiki/Brent%27s_method) article.
!!
!! @note The result depends on xb, because x_i does not necessarily have
!!       to be monotonic. The result should be the closest value to xb.
!!
!! @author M. Reichert
!! @date 16.10.2024


!>
!! Initialize the readini module and open files.
!!
!! Depending on user defined parameters
!! (e.g., \ref parameter_class::custom_snapshots)
!! this subroutine calls several subroutines to read
!! input files. After reading the files, it calls
!! \ref consistency_check to make a couple of checks and
!! raise an error if something is not correct.
!!
!! @author: Moritz Reichert
!!
!! \b Edited: 28.02.17


!>
!! @brief Read in times for snapshots.
!!
!! These times should be given by a separate file
!! with the parameter \ref parameter_class::custom_snapshots.
!! The units in this file is days. The subroutines that are based on
!! the custom snapshots assume a sorted time array and it is therefore
!! sorted in the end of this subroutine. An example of the file could be:
!! \file{
!! 1.1574074074074073e-04
!! 0.0208333
!! 1  }
!! This would output a snapshot at 10 s, 30 min, and 1 day.
!!
!! @see timestep_module::restrict_timestep, analysis::output_iteration
!!
!! @author Moritz Reichert
!!


!>
!! @brief Reads in nuclei that will be tracked and where the abundance will
!! be stored in a separate file.
!!
!! If parameter_class::track_nuclei_every is larger than 0,
!! a file will be created, containing the information of the abundances of the nuclei.
!! This is based on the input parameter \ref parameter_class::track_nuclei_file
!! that contains a path to a file with the format of the nuclei being the same
!! as the format of the sunet file. An example could be:
!! \file{
!!  c13
!! ti44
!! ni56 }
!!
!! @note Verbose level greater than 2 will create the file _debug_track_nuclei.dat_
!! to debug this subroutine.
!!
!! @author Moritz Reichert
!!
!! \b Edited:
!!     - 09.06.17
!!     - 03.10.24 - MR
!! .


!>
!! @brief Reads in seed abundances from file \ref parameter_class::seed_file
!!
!! The input file can have a custom format specified by \ref parameter_class::seed_format.
!! For the seed_format "name X" The file would look like:
!! \file{
!! \# I'm a comment
!!    n       2.000000e-01
!!    p       1.000000e-01
!!  c12       2.000000e-01
!!  o16       3.000000e-01
!! ca40       1.500000e-01
!! tc98       0.500000e-01 }
!!
!! Note that empty lines or lines starting with "#" at the beginning of the file are skipped.
!! Another example for seed format "A Z X skip" looks like:
!! \file{
!!    1   0    2.000000e-01  unimportant
!!    1   1    1.000000e-01  unimportant
!!   12   6    2.000000e-01  unimportant
!!   16   8    3.000000e-01  unimportant
!!   40  20    1.500000e-01  unimportant
!!   98  48    0.500000e-01  unimportant }
!!
!! If the mass fractions do not sum up to one, this subroutine will rescale
!! them. In order to make this routine work, also
!! \ref parameter_class::read_initial_composition has to be set to "yes".
!!
!! @see parameter_class::seed_file, parameter_class::seed_format
!! @author Moritz Reichert
!!
!! @remark This subroutine replaced the previous "read_seed_urs" subroutine of
!!         M. Ugliano.
!!
!! \b Edited:
!!         - 01.06.22 - MR
!! .


!>
!! Function to convert from a given time unit to seconds.
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = time_unit_conversion("ms")
!!~~~~~~~~~~~~~~
!! b will be \f$ 10^{-3} \f$ as it is the conversion from ms to s.
!!
!! @note New time units can be defined here.
!!
!! @author Moritz Reichert


!>
!! Function to convert from a given temperature unit to GK
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = temp_unit_conversion("K")
!!~~~~~~~~~~~~~~
!! b will be \f$ 10^{-9} \f$ as it is the conversion from K to GK.
!!
!! @note New temperature units can be defined here.
!!
!! @author Moritz Reichert


!>
!! Function to convert from a given density unit to g/ccm
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = dens_unit_conversion("g/m^3")
!!~~~~~~~~~~~~~~
!! b will be \f$ 10^{-6} \f$ as it is the conversion from g/m^3 to g/ccm.
!!
!! @note New density units can be defined here.
!!
!! @author Moritz Reichert


!>
!! Function to convert from a given distance unit to km
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = dist_unit_conversion("km")
!!~~~~~~~~~~~~~~
!! b will be \f$ 1 \f$ as it is the conversion from km to km.
!!
!! @note New distance units can be defined here.
!!
!! @author Moritz Reichert


!>
!! Function to convert from a given neutrino temperature unit to MeV
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = nutemp_unit_conversion("mev")
!!~~~~~~~~~~~~~~
!! b will be \f$ 1 \f$ as it is the conversion from Mev to Mev.
!!
!! @note New (anti-)neutrino temperature units can be defined here.
!!
!! @author Moritz Reichert


!>
!! Function to convert from a given neutrino energy unit to neutrino temperatures in MeV
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = nuenergy_unit_conversion("mev")
!!~~~~~~~~~~~~~~
!! b will be \f$ 3.15^{-1} \f$ as it is the conversion from neutrino energies to
!! neutrino temperatures (assuming average energies).
!!
!! @note New (anti-)neutrino energy units can be defined here.
!!
!! @author Moritz Reichert


!>
!! Function to convert from a given neutrino luminosity unit to erg/s
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = nulumin_unit_conversion("erg/s")
!!~~~~~~~~~~~~~~
!! b will be \f$ 1 \f$ as it is the conversion from erg/s to erg/s.
!!
!! @note New (anti-)neutrino luminosity units can be defined here.
!!
!! @author Moritz Reichert


!>
!! Reads the trajectory file.
!!
!! The columns and structure of the file is determined by the user
!! defined parameter \ref parameter_class::trajectory_format.
!! The default trajectory format is given by: <b> "time temp dens rad ye" </b>.
!! This format will assume a file that looks like:
!! \file{
!! \#time[s], T9[GK], density[g/cm^3], R[km], Ye
!! \#--------------------------------------------
!! 0.0000e+00 1.0965e+01 8.7096e+12 4.9273e+01 0.03488
!! 2.5000e-05 9.9312e+00 7.4131e+12 5.0361e+01 0.03488
!! ...}
!! A more complex format, <b> "time:ms x y z log_dens log_temp:K ye" </b>, would assume a file like:
!! \file{
!! \#t [ms]       x[km]       y[km]      z[km]      log(rho[cgs]) log(T[K])   Ye
!! \#----------------------------------------------------------------------------------
!!  0.0000E+00  0.1051E+02  0.3774E+01 -0.4538E+01  0.1364E+02  0.1016E+02  0.1604E-01
!!  0.2521E-01  0.1046E+02  0.4724E+01 -0.4541E+01  0.1363E+02  0.1060E+02  0.1604E-01
!! ...}
!! Neutrino luminosities and energies are also read here. A format could look like:
!! <b> "time temp dens rad ye lnue lanue tnue tanue" </b>. \n
!! Possible column names are:
!! <pre style="line-height:.3">
!! - time   : The time (s) of the trajectory
!! - temp   : The temperature (GK) of the trajectory
!! - dens   : The density (g/ccm) of the trajectory
!! - rad    : The radius (km) of the trajectory
!! - x,y,z  : x, y, and z coordinates (km) of the trajectory
!! - ye     : The electron fraction
!! - lanue  : Anti-electron neutrino luminosities (erg/s)
!! - lnue   : Electron neutrino luminosities (erg/s)
!! - tanue  : Anti-electron neutrino temperatures (MeV)
!! - tnue   : Electron neutrino temperatures (MeV)
!! - eanue  : Anti-electron neutrino energies (MeV)
!! - enue   : Electron neutrino energies (MeV)
!! - lanux  : Anti-neutrino luminosities of heavy neutrinos (erg/s)
!! - lnux   : Neutrino luminosities  of heavy neutrinos (erg/s)
!! - tanux  : Anti-neutrino temperatures  of heavy neutrinos (MeV)
!! - tnux   : Neutrino temperatures of heavy neutrinos (MeV)
!! - eanux  : Anti-neutrino energies of heavy neutrinos (MeV)
!! - enux   : Neutrino energies of heavy neutrinos (MeV)
!! - skip   : skip a column
!! .
!! </pre>
!!
!! @note Lines starting with "#" or blank lines are skipped
!!
!! @author Moritz Reichert
!!
!! \b Created: 17.12.20


!>
!! Make tests to ensure the trajectory is okay.
!!
!! Otherwise complain. Tests are, for example, the occurence of
!! negative radii at some point or check if the electron fraction
!! is out of bounds (\f$ 0 \le y_e \le 1 \f$).
!!
!! @author Moritz Reichert


!>
!! Readini cleanup subroutine
!!
!! At the moment, the subroutine does nothing.
!!
!! @author Moritz Reichert
!!
!! \b Edited:
!!       - MR 28.02.2017
!!       - OK 18.06.2017
!! .


!> Initialize theoretical weak rates
!!
!! This subroutine set the flag weak and calls
!! the necessary subroutines to read the rates.
!!
!! @author Moritz Reichert
!! @date 24.01.21


!> Calculate derivatives of weak reactions
!!
!! These derivatives are necessary for the bicubic interpolation.
!!
!! @author: M. Reichert


!> Merge theoretical weak rates into larger rate array.
!!
!! This merge is partly done instantaneously and partly when
!! the temperature reaches parameter_class::reload_exp_weak_rates.


!> Read the theoretical weak rates from a unformatted binary file
!!
!! In case the binary file is read, no other data has to be read.
!!
!! @author M. Reichert
!! @date 27.07.21


!> Save the theoretical weak rates to a unformatted binary file
!!
!! @author M. Reichert
!! @date 27.07.21


!> Calculate the theoretical weak rate.
!!
!! For \ref parameter_class::iwformat equal to 1, this routine interpolates
!! the rate on the temperature - density grid. Otherwise, for parameter_class::iwformat
!! equal 2, this subroutine calculates the effective phase space integral to translate
!! the tabulated log <ft> values to actual rates. For this also the chemical
!! potential has to be known.
!!
!! \b Edited:
!!    - 26.07.22, MR: Created this subroutine from previously existing code in Jacobi_init
!! .
!!
!! @warning In case of \ref parameter_class::iwformat equal to two
!!          and using timmes chemical potential (\ref parameter_class::use_timmes_mue)
!!          \ref mue has to be calculated prior to calling this subroutine.


!> Reads and counts the amount of theoretical weak rates
!!
!! Furthermore, this routine creates the rrate_weak array that is
!! merged into the total rate array rrate.
!!
!! \b Edited:
!!   - 24.01.21, MR - copied it into this separate subroutine
!! .


!>
!! Reads weak reaction rates in log format
!!
!! This subroutine is called when parameter_class::iwformat was
!! set to 1. It assumes weak reaction rates that are
!! logarithmic. It will fill the global_class::weak_rate array
!! with rates that are later indicated by the label " ffn". An example
!! of the file that is read here is given by:
!! \file{
!! neg. daughter Sc45 z=21 n=24 a=45 Q=  0.7678
!! pos. daughter Ca45 z=20 n=25 a=45 Q= -0.7678
!!                      +++ Sc45 --> Ca45 +++      --- Ca45 --> Sc45 ---
!!   t9   lrho    uf    lbeta+    lfte-     lnu    lbeta-    lfte+   lnubar
!!  0.01  1.0  -0.003  -99.999  -99.999  -99.999   -7.302  -99.999   -0.746
!!  0.10  1.0  -0.058  -91.517    5.796   -1.577   -7.302    7.565   -0.746
!!  0.20  1.0  -0.134  -49.637    5.792   -1.266   -7.302    7.083   -0.746
!!  ... }
!!
!! @remark Some rates in the file will replace rates from the reaclib, changing them there may not
!!         have an effect as other rates are used then.
!!
!! @see parameter_class::temp_reload_exp_weak_rates, parameter_class::iwformat
!!
!! \b Edited:
!!        - 12.01.14
!!        - 11.03.22 (MR: extended routine for more general grids)
!! .


!>
!! Set wk_index for given T, @f$\rho@f$ and @f$Y_e@f$
!! The index is written into module variable \ref wk_index
!!
!! After the subroutine has been called the correct indices for a two
!! dimensional interpolation are stored in \ref wk_index.
!!
!! @see weak_inter, readweak_logft, parameter_class::iwinterp, inter_module::get_indice_2D
!!
!! \b Edited:
!!     - MR : 19.01.2021 - Removed hard coded temperatures
!!     - MR : 11.03.2022 - Rates are now on two dimensional grid, rewrote this routine
!!     - MR : 06.07.2022 - Moved things to inter_module, now it is only an interface
!! .


!> Interpolation interface.
!!
!! This function interpolates the weak rates either bilinear or bicubic
!!
!! @author: M. Reichert
!! @date: 14.03.22
!!
!! @warning The bicubic interpolation fails at values where -99 is neighboring.
!!          There, it produces artifacts. For mue, it is, however, okay.
!!
!! \b Edited:
!!     - MR : 06.07.2022 - Moved things to interpolation module
!! .


!>
!! This routine is used to replace theoretical weak rates with experimental ones
!! it's called when T9 < parameter_class::temp_reload_exp_weak_rates (default 1d-2)
!!
!! @remark Some rates will replace rates from the reaclib, changing them there may not
!!         have an effect for low temperatures as other rates are used then.
!!
!! @see parameter_class::temp_reload_exp_weak_rates, parameter_class::iwformat
!!      weak_index, weak_inter, temp_grid_weak
!!
!! \b Edited:
!!     - 27.01.21, M.R.
!!     - 23.03.23, M.R.
!! .


!< Debug routine to output n <-> p reactions
!!
!! This routine creates the file "np_twr.dat", containing a variety of
!! interpolated <ft> values. This can be useful to test the implemented
!! interpolations.
!!
!! @author: M. Reichert
!! @date: 05.07.22


!----------------------------Auxiliary helper functions---------------------!
!---------------------------------------------------------------------------!
!> Sorts the entries in weak_rate in increasing order of the decaying nuclide
!!


!> Initialize tabulated rates
!!
!! This subroutine creates the shorthand flag "tabulated"
!! to indicate that tabulated rates are used,
!! reads and counts the tabulated rates
!!
!! @author Moritz Reichert
!! @date 24.01.21
!!
!! \b Edited:
!!   - 04.10.23, M. Jacobi - support for flexible tabulated temperature grids
!! .


!> Write the verbose output of the reaction rates
!!
!! The rates are always counted, for a certain verbose level they
!! are also printed to the OUT file
!!
!! @author M. Reichert
!! @date 27.01.21


!> Merge tabulated rates into larger rate array.
!!
!! This subroutine merges and replaces rates from the input array with
!! tabulated rates from \ref tabulated_rate.
!!
!! @author D. Martin
!!
!! \b Edited:
!!  - M. Reichert (25.01.21): Made it a separate subroutine
!!  - M. Reichert (05.08.22): Temporary save rates in other array
!! .


!> Calculates the tabulated rate.
!!
!! This subroutine serves as an interface between the tabulated_rate_module
!! and the jacobian class. It interpolates the rate on the grid and returns
!! the rate value at a given temperature
!!
!! \b Edited:
!!  - 26.07.22, MR: Created this subroutine to be in line with the other
!!                  reaction rate types.
!!  - 04.10.23, MJ: Added support for flexible tabulated temperature grids
!! .


!> Multiply a tabulated rate by a factor
!!
!! This subroutine multiplies a tabulated rate by a factor.
!!
!! @author M. Reichert
!! @date 04.06.24


!> Reads tabulated reaction rate temperature grid.
!!
!! If tabulated_temperature_file is not given, a default
!! temperature grid is used.
!!
!! @see parameter_class::use_tabulated_rates,
!!      parameter_class::tabulated_temperature_file
!!
!! \b Edited:
!!     - 04.06.24, MR: - Added check for monotonicity
!! .
!!
!! @author M. Jacobi


!>
!! Reads tabulated reaction rates.
!!
!! The tabulated reaction rate file is given in the same
!! chapter style as a usual reaclib file, but has different entries
!! instead of the fit values. The temperature grid of the tabulated reactions
!! if given with nucstuff_class::temp_grid_tab . This function is only called
!! if parameter_class::use_tabulated_rates is set to true. An example file
!! could look like:
!! \l_file{...
!!       be7    n  be6                       tabln    -1.06774e+01
!! 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 1.323e-94 1.437e-76 1.129e-63 5.421e-54 1.868e-46 2.028e-40 2.890e-22 3.813e-13 1.201e-07 5.800e-04 2.562e-01 2.534e+01 1.669e+04 1.341e+06 3.232e+07 3.659e+08 2.502e+09 1.201e+10 }
!!
!! @see parameter_class::use_tabulated_rates,
!!      parameter_class::tabulated_rates_file
!!
!! @author D. Martin
!!
!! \b Edited:
!!      - 14.04.15
!!      - 23.01.21, MR - set the source to always "tabl"
!!      - 17.07.22, MR - introduced custom reading format,
!!                       depending on length of the temperature grid
!!      - 04.10.23, MJ - support for flexible tabulated temperature grids
!!      - 31.05.24, MR - Fixed bug related to reading rates.
!! .


!> Interpolate tabulated rates from the table
!!
!! This function uses a lin-log interpolation to calculate
!! a given reaction rate (contained in \ref parameter_class::tabulated_rates_file)
!! An example entry of a tabulated rate looks like:
!!
!! \l_file{...
!!       be7    n  be6                       tabln    -1.06774e+01
!! 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 1.323e-94 1.437e-76 1.129e-63 5.421e-54 1.868e-46 2.028e-40 2.890e-22 3.813e-13 1.201e-07 5.800e-04 2.562e-01 2.534e+01 1.669e+04 1.341e+06 3.232e+07 3.659e+08 2.502e+09 1.201e+10 }
!!
!! @note The function contains also a log-log interpolation that is commented out
!!       and that can be replaced with the current lin-log interpolation.
!!
!! @warning This function should be changed in case of a different temperature grid
!!          for tabulated rates
!!
!! @see tabulated_inter, temp_grid_tab, parameter_class::use_tabulated_rates,
!!      parameter_class::tabulated_rates_file
!!
!! @author D. Martin


!>
!! @brief Set \ref tab_index for a given temperature
!!
!! Sets the indices for the tabulated rate interpolation
!! in \ref tabulated_inter. Temperature values below or above the
!! temperature grid will result in two equal indices
!! with either 1 or the last index, respectively.
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! temp = 7e-4
!! call tabulated_index(temp)
!! write(*,*) tab_index(1), tab_index(2)
!!~~~~~~~~~~~~~~
!! will output 2 and 3.
!!
!! @returns \ref tab_index, array with indices for interpolation
!!
!! @see tabulated_inter, temp_grid_tab, parameter_class::use_tabulated_rates,
!!      parameter_class::tabulated_rates_file, readtabulated
!!
!! @author D. Martin


!> Read the tabulated rates from a unformatted binary file
!!
!! In case the binary file is read, no other data has to be read.
!!
!! @author M. Jacobi
!! @date 04.10.23


!> Save the theoretical tabulated rates to a unformatted binary file
!!
!! @author M. Jacobi
!! @date 04.10.23


!> Determines the position of jacobian entries in the cscf value array.
!!
!! This subroutine creates the basic sparse format of the jacobian. For this
!! it writes a dummy matrix with entries = 1 at places in the matrix
!! that are connected via nuclear reaction rates. Afterwards the matrix
!! is stored in compressed sparse column format (cscf) into the arrays
!! \ref vals, \ref rows, and \ref pt_b.
!! In cscf format, the matrix:
!! \f[
!! X= \left( \begin{array}{cccc}
!!          9 & 8 & 0 & 2\\
!!          0 & 0 & 0 & 5\\
!!          0 & 3 & 0 & 0\\
!!          5 & 0 & 4 & 9\end{array} \right).
!! \f]
!! will be stored like
!! \f[ \mathrm{vals} =[9,5,8,3,4,2,5,9] \f]
!! with vals storing the non-zero values of X,
!! \f[ \mathrm{rows} = [1,4,1,3,4,1,2,4] \f]
!! rows storing the position of a new row in vals, and
!! \f[ \mathrm{pt\_b} = [1,3,5,6,9] \f].
!! the position of the columns of the non-zero entries.
!!
!! @see [Winteler 2013](https://edoc.unibas.ch/29895/), section 2.4.2
!!
!! \b Edited:
!!     - 11.01.14
!!     - 28.07.22, MR: introduced new chapters
!! .


!>
!! The solver core
!!
!! This subroutine calls the sparse PARDISO solver
!! [intel pardiso](https://software.intel.com/en-us/node/470282) to
!! solve equations in the following form:
!! \f[ J\cdot \mathrm{res} = \mathrm{rhs}  \f]
!! with res being the unknown. In addition, this subroutine
!! checks for zero entries in vals and adjusts the sparse
!! format accordingly.
!!


!>
!! Main initialising subroutine. calls reading subroutines and fills the
!! reactionrate array.
!!
!! Reads included nuclei, Reaclib, theoretical weak rates,
!! neutrino rates, tabulated rates, fission rates (and more)
!! and prepares in this way the reaction rates
!! \ref global_class::rrate.
!!
!! @returns \ref global_class::rrate
!!
!! \b Edited:
!!      - 14.04.15
!!      - OK 15.06.17, made into a module
!! .


!>
!! Create a folder with binary files that contain all necessary reaction data
!!
!! This routine creates binary files in the exact format that WinNet needs to
!! initialize the rate arrays. The reading of these files can be done much faster
!! then reading the original files. The files are stored in the folder specified
!! by the path argument. The folder is created if it does not exist.
!! Using these files is specifically useful when running many trajectories.
!!
!! @author M. Reichert
!! @date 21.07.23


!>
!! Switches between NSE and network modes (EM_NSE / EM_NETHOT / EM_NETCOLD)
!!
!! The following conditions are included to switch the evolution mode:
!!
!!

!!
Evolution mode switches

!!
 Evolution mode  Condition
!!
 EM_NSE          \f$T_9\f$ > parameter_class::nsetemp_hot
!!
 EM_NETHOT       parameter_class::temp_reload_exp_weak_rates < \f$T_9\f$ < parameter_class::nsetemp_cold
!!
 EM_NETCOLD      \f$T_9\f$ < parameter_class::temp_reload_exp_weak_rates
!!
 EM_TERMINATE    Depends on termination criterion, see parameter_class::termination_criterion
!!

!!
!! The following figure illustrates the different regions for an example trajectory:
!! @image html temperature_regimes.png width=400px
!!
!! @note This subroutine also changes the timestep at the transition from NSE
!!       to the network. For the gear solver, gear_module::set_timestep
!!       has to be called.
!!
!! @todo At this point it could be useful to check here the difference
!! between the saved value of dYdt from the network and the dYdt
!! calculated by the nse abchange function, right after the network->nse
!! switch
!!
!! @see single_zone_vars::evolution_mode
!!
!! \b Edited:
!!      - 17.12.16
!! .


!>
!! Print an overview of the reactions involved in the calculation.
!!
!! An example file (_debug_all-reactions.txt_ ) looks like:
!! \file{...
!! O N E P A R T I C L E R E A C T I O N S
!! 1         n --->    p                              Q=  0.782 MEV     ffn
!! Reaction type: weak
!! 2         n --->    p                              Q=  0.000 MEV     nen
!! Reaction type: neutrino
!! 3         p --->    n                              Q= -0.782 MEV     ffn
!! Reaction type: weak
!! ...}
!!
!! Furthermore, a file ( _debug_weak-reactions.txt_ ) containing all
!! weak reactions is created that looks like:
!! \file{
!! OVERVIEW OF ALL WEAK-REACTIONS IN THE NETWORK
!! 1         n --->    p                              Q=  0.782 MEV     ffn
!! 2         n --->    p                              Q=  0.000 MEV     nen
!! 3         p --->    n                              Q= -0.782 MEV     ffn
!! 4         p --->    n                              Q=  0.000 MEV    nebp }
!!
!! @note Fission reactions do not obey the default reaclib format and are not
!!       visualized correct.
!!
!! \b Edited:
!!     - MR: 21.01.21 - included interface (get_net_name) to net_names instead of accessing it directly


!> Print a debug file of the reaction
!!
!! In contrast to \ref print_reactions, this subroutine prints additional flags
!! of a reaction. The structure of a file looks like:
!!
!!

!!
File structure

!!
 Reaclib chapter                 isotope names  Q-Value  Source label
!!
 Amount destroyed/synthesized    double counting factor
!!
"is_weak"  "is_resonant"  "is_reverse"
!!

!! An example of the file (_debug_reac.dat_) looks like:
!! \file{...
!! 5     n na32    p ne32            -16.606  rath
!! -1 -1  1  1  0  0      1.000
!!     F    F    T
!! 5     p na32    n mg32             18.317  rath
!! -1 -1  1  1  0  0      1.000
!!     F    F    F
!! ...}
!!


!> Initialize everything for the inverse rates
!!
!! This subroutine analyzes the parameters to determine which rates have to
!! be replaced and which Q-value has to be used.
!!
!! @author M. Reichert
!! @date 04.08.22


!> Delete and create new inverse rates
!!
!! This routine first identifies included reverse rates and deletes them.
!! Afterwards, new reverse rates are created and attached to the rate array at the end.
!! The position of the rates at the end of the array is important as they will use the
!! previously calculated forward rates. Weak reactions, fission, and chapter 7
!! reactions do not have any inverse reaction. This routine also stores
!! the index of the forward reaction in %param(1).
!!
!! @author  M. Reichert
!! @date 22.07.22


!> Routine to create an inverse rate, based on the forward rate.
!!
!! Writes the correct nuclei in the parts array of each reaction.
!! Furthermore, as the %param() array of the rates is not used, it is redefined to contain:
!!  - 1: Index to forward rate in rate array
!!  - 2: #Products - #Reactants.
!!  - 3: \f$ 1.5 \cdot \log(A_{r1} \cdot ...) / (A_{p1} \cdot ...) \f$,  with A_r being
!!       the mass number of the reactants and A_p of the products.
!!  - 4: \f$ 1.5 \cdot \log(M_u/(2.0\cdot \pi \cdot \hbar^2)) \f$.
!!  - 5: \f$ - \log((2J_{r1}+1) \cdot ...) / ((2J_{p1}+1) \cdot ...) \f$,  with J_r being
!!       the spin of the reactants and J_p of the products.
!! . Additionally, the Q-value is calculated from the mass excess.
!!
!! @author  M. Reichert
!! @date 22.07.22


!> Calculate the inverse rate from the forward one via detailed balance.
!!
!! This subroutine calculates the inverse rate via detailed balance. Detailed balance
!! gives a direct relation between forward and inverse reaction.
!!
!! @note This subroutine also sets a threshold for inverse rates in case the Q-value
!!       for a photodissociation is positive. In this case the rates can diverge towards
!!       lower temperatures. This can mess up convergence of the system due to precision errors.
!!       For the default FRDM winvn/reaclib q-values this is not a problem, however, when
!!       using other mass models or when varying the masses it can become a problem.
!!
!! @see [Fowler, Caughlan, and Zimmerman (1967)](https://www.annualreviews.org/doi/10.1146/annurev.aa.05.090167.002521)
!! @author  M. Reichert
!! @date 22.07.22
!!
!! \b Edited:
!!   - 18.11.22; M.R: implemented more restrictive cutoff for the rates in case of
!!                    positive q-values
!! .


!> Verbose routine to output one inverse reaction of chapter 4-9
!!
!! This subroutine outputs one forward, one calculated inverse, and
!! the same inverse as given by the reaclib for chapter 4-9.
!! All other chapters do not have forward rates so far.
!! The calculated inverse and reaclib inverse should to large extends
!! agree. There might be a small deviation due to different q-values
!! used in the reaclib and in the winvn. This routine is only
!! called when verbose_level is greater or equal two.
!!
!! @note For all chapter 7 reactions, the double counting factor seems
!!       to be missing in the inverse rate of Reaclib (31.7.2022).
!!
!! @author M. Reichert
!! @date 30.07.22


!> Write the verbose output of the reaction rates
!!
!! The rates are always counted, for a certain verbose level they
!! are also printed to the OUT file
!!
!! @author M. Reichert
!! @date 21.07.22


!> Initialize the fission reactions
!!
!! This subroutine counts and reads fission reactions.
!! After calling it \ref fissrate will be filled as well as the integer
!! \ref nfiss will store the amount of fission reactions.
!!
!! @author M. Reichert
!! @date 25.01.21


!> Check the mass conservation during the fission process.
!!
!! This subroutine ensures that the total number of nucleons is conserved
!! during fission reactions. It calculates the number of nucleons created
!! and destroyed for each fission rate, checks for discrepancies against
!! a defined error threshold, and raises an exception if the mass
!! conservation is violated. If small deviations are within the threshold,
!! the subroutine rescales the fragments accordingly.
!!
!! @author M. Reichert
!! @date 17.10.24


!> Reorder the fission fragments
!!
!! Subroutine to reorder the fragments, having the ones with the largest
!! ch_amount at the beginning. This is benificial as we can ignore
!! some of the entries in the jacobian in case the parent abundance
!! is zero.
!!
!! @author M. Reichert
!! @date 22.02.23


!> Read the fission reactions and fragment distributions from a binary file
!!
!! This subroutine reads the fission reactions and fragment distributions
!! from a binary, unformatted file. The file is assumed to be created
!! beforehand. It is only read when use_prepared_network is set to true.
!!
!! @author M. Reichert
!! @date 21.07.23


!> Save the fission data to a unformatted binary file
!!
!! This subroutine saves the fission data to a unformatted binary file.
!!
!! @author M. Reichert
!! @date 21.07.23


!> Merge fission rates with larger array.
!!
!! This subroutine will merge the fission rates.
!! Since fission rates are treated separately, there is not really much
!! to do. However, in case of beta-delayed fission, the half lifes
!! of the beta decays have to be modified to include the fission rates.
!!
!! @note The other fission rate array \ref fissrate will exist independently
!!       and are used to calculate the correct equations for the
!!       fission fragments in \ref jacobian_class::jacobi_init,
!!       \ref jacobian_class::abchange.
!!
!! @author M. Reichert
!! @date 25.01.21


!> Modifies half lifes of beta decays to include fission
!!
!! In case the beta delayed fission rates are given as a probability,
!! the beta decays are rescaled to include the fission rates without
!! changing the total half life.
!! The fission rates are given by:
!! \f[
!! \lambda_{\text{fiss}} =P_{\text{fiss}} * \lambda_{\beta}
!! \f]
!! where \f$P_{\text{fiss}}\f$ is the probability of fission and
!! \f$\lambda_{\beta}\f$ is the beta decay rate as given initially
!! in the Reaclib. The beta decay rate is then modified to
!! \f[
!! \lambda_{\beta, new} = \left(1-P_{\text{fiss}}\right) * \lambda_{\beta}
!! \f]
!! There are special cases to consider, namely \f$P_{\text{fiss}}=1\f$ in
!! which case the reaclib rate has to be removed completely and
!! \f$\lambda_{\beta}\f = 0$ in which case the fission rate has to be removed.
!! Note also that fission can have multiple channels, which are by emitting
!! different amount of neutrons.
!! The fission rates in form of probabilities are given, e.g., in
!! [Panov et al. 2005](https://ui.adsabs.harvard.edu/abs/2005NuPhA.747..633P/abstract) or
!! [Mumpower et al. 2018](https://ui.adsabs.harvard.edu/abs/2018ApJ...869...14M/abstract).
!!
!! @author M. Reichert
!! @date 30.05.24


!> Count the amount of fission rates
!!
!! This subroutine counts the amount of fission rates and
!! stores the result in \ref nfiss.
!! In case that a new fission type will be implemented,
!! the reaction rates should be counted here.
!! The different formats for the different types of fission reactions are:
!!

!!
Fission formats

!!
 Type                 Value  Description
!!
 Spontaneous          0      No rates are read
!!
 Spontaneous          1      Reaclib format
!!
 Spontaneous          2      Half life format
!!
 n-induced            0      No rates are read
!!
 n-induced            1      Reaclib format
!!
 \f$\beta\f$-delayed  0      No rates are read
!!
 \f$\beta\f$-delayed  1      Reaclib format
!!
 \f$\beta\f$-delayed  2      Half life format
!!
 \f$\beta\f$-delayed  3      Probability format
!!

!!
!! @see \ref read_fission_rates
!!
!! @author M. Reichert
!! @date 25.01.21


!> Count the amount of fission rates in reaclib format
!!
!! This subroutine counts the amount of fission rates in reaclib format
!! and stores the result in count_rates. This is necessary to allocate
!! the fission array with the correct length. The subroutine can be called
!! for any kind of fission (spontaneous, n-induced, beta-delayed).
!!
!! \b Edited:
!!    - 30.05.2024 (MR): Made this its own subroutine to add more file formats
!! .


!> Count the amount of fission rates in half-life format
!!
!! This subroutine counts the amount of fission rates in half-life format
!! and stores the result in count_rates. This is necessary to allocate
!! the fission array with the correct length. The subroutine can be called
!! for spontaneous and beta-delayed fission.
!! An example of an entry can be:
!! \file{
!!  th198    4.760787e-09    kh20
!!  th199    2.808520e-08    kh20
!!  th200    2.841403e-08    kh20
!! ...}
!! where the first columns gives the nucleus, the second the halflife in seconds
!! and the third the source. Note that in this format, no beta-delayed neutrons
!! can be specified.
!!
!! @author M. Reichert
!! @date 30.05.24


!> Count the amount of fission rates in probability format
!!
!! This subroutine counts the amount of fission rates in probability format
!! and stores the result in count_rates. This is necessary to allocate
!! the fission array with the correct length. The subroutine can be called
!! for beta-delayed fission.
!! An example of an entry can be:
!! \file{
!! pa291        mp18
!! 0.000    0.008    0.000    0.015    0.000    0.018    0.000    0.025    0.000    0.003
!! pa292        mp18
!! 0.000    0.001    0.002    0.000    0.004    0.000    0.006    0.000    0.018    0.000
!! pa293        mp18
!! 0.239    0.001    0.000    0.009    0.000    0.010    0.000    0.014    0.000    0.009
!! ...}
!! where the first line of an entry gives nucleus name and the source. The second line
!! gives the probabilities of the fission channels (i.e., P0nf, P1nf, ...).
!! Note that there is a maximum number of columns (i.e., neutron emission) set to 30 here.
!! Throughout the file, the amount of possible channels have to stay the same, but they
!! can be different for two different files. For example, for Panov et al. 2005 the file
!! could look like:
!! \file{
!!  u259        pa05
!! 0.990
!!  u260        pa05
!! 0.020
!!  u261        pa05
!! 0.990
!! ...}.
!!
!! @author M. Reichert
!! @date 30.05.24


!> Initializes the rates with fragments
!!
!! This routine initializes the fission rates with the specified fragments.
!! The fragments can differ for the types of fission.
!!
!!
!!
!!
!! \b Edited:
!!     - 31.05.2024 (MR): Created this subroutine from code parts contained in other routines
!! .


!> Read the fission rates, splitted into different types of fission
!!
!! This routine serves as interface between the reading routines and
!! the different fission formats and types. In case a new type of
!! fission will be implemented, the reaction rates should be read here.
!! The different formats for the different types of fission reactions are:
!!

!!
Fission formats

!!
 Type                 Value  Description
!!
 Spontaneous          0      No rates are read
!!
 Spontaneous          1      Reaclib format
!!
 Spontaneous          2      Half life format
!!
 n-induced            0      No rates are read
!!
 n-induced            1      Reaclib format
!!
 \f$\beta\f$-delayed  0      No rates are read
!!
 \f$\beta\f$-delayed  1      Reaclib format
!!
 \f$\beta\f$-delayed  2      Half life format
!!
 \f$\beta\f$-delayed  3      Probability format
!!

!!
!! @author M. Reichert
!! @date 31.05.2024


!> Reads fission rates in Reaclib format
!!
!! This subroutine reads the fission rates that are specified in the file
!! parameter_class::fission_rates. Fission rates are implemented with the same
!! fits and a similar format as usual reaclib rates (see reaclib_rate_module::read_reaclib).
!! An example looks like:
!! \file{
!!    th256                                 ms99w     0.00000E+00
!! 1.988512E-02 0.000000E+00 0.000000E+00 0.000000E+00
!! 0.000000E+00 0.000000E+00 0.000000E+00
!!    th257                                 ms99w     0.00000E+00
!! -1.483947E+00 0.000000E+00 0.000000E+00 0.000000E+00
!! 0.000000E+00 0.000000E+00 0.000000E+00
!! ...}
!! The chapter structure is the same as in reaclib, but only the parent nucleus
!! has an entry. The products are given by the respective fission fragment
!! distribution.
!!
!! @returns \ref fissrate filled with fission rates
!! @author M. Eichler
!!
!! \b Edited:
!!   - 25.01.21 (MR): Moved from init_network to this new independent subroutine
!!   - 27.05.24 (MR): Moved initializing fragments to independent subroutine
!! -


!> Read the fission rates in probability format
!!
!! This subroutine reads fission rates in probability format
!! and stores the result in count_rates. The subroutine can be called
!! for beta-delayed fission and will throw an error for other types of fission.
!! An example of an entry can be:
!! \file{
!! pa291        mp18
!! 0.000    0.008    0.000    0.015    0.000    0.018    0.000    0.025    0.000    0.003
!! pa292        mp18
!! 0.000    0.001    0.002    0.000    0.004    0.000    0.006    0.000    0.018    0.000
!! pa293        mp18
!! 0.239    0.001    0.000    0.009    0.000    0.010    0.000    0.014    0.000    0.009
!! ...}
!! where the first line of an entry gives nucleus name and the source. The second line
!! gives the probabilities of the fission channels (i.e., P0nf, P1nf, ...).
!! Note that there is a maximum number of columns (i.e., neutron emission) set to 30 here.
!! Throughout the file, the amount of possible channels have to stay the same, but they
!! can be different for two different files. For example, for Panov et al. 2005 the file
!! could look like:
!! \file{
!!  u259        pa05
!! 0.990
!!  u260        pa05
!! 0.020
!!  u261        pa05
!! 0.990
!! ...}.
!!
!! @author M. Reichert
!! @date 31.05.24


!> Read fission rates in half-life format
!!
!! This subroutine reads fission rates in half-life format.
!! The subroutine can be called for spontaneous and beta-delayed fission
!! and throws an error otherwise.
!! An example of an entry can be:
!! \file{
!!  th198    4.760787e-09    kh20
!!  th199    2.808520e-08    kh20
!!  th200    2.841403e-08    kh20
!! ...}
!! where the first columns gives the nucleus, the second the halflife in seconds
!! and the third the source. Note that in this format, no beta-delayed neutrons
!! can be specified.
!!
!! @author M. Reichert
!! @date 30.05.24


!> Determines fission fragment mass distribution as described in Panov et al. 2001.
!!
!! This routine is called for \ref parameter_class::fissflag = 1 and fills
!! the array \ref fissrates with indices of the fragment nuclei.
!!
!! @see [Panov et al., Nuc. Phys. A688 2001](https://ui.adsabs.harvard.edu/abs/2001NuPhA.688..587P/abstract)
!! @author C. Winteler


!>
!! Kodama-Takahashi distribution
!!
!! Subroutine that calculates fission fragment distribution as
!! described in Kodama & Takahashi, Nuc. Phys. Sec.A, Vol. 239,
!! Issue 3, p. 489-510, 1975.
!!
!! @see [Kodama & Takahashi 1975](https://ui.adsabs.harvard.edu/abs/1975NuPhA.239..489K/abstract)
!!
!! \b Edited:
!!      - 11.01.14
!!      - 05.12.17 (ME)
!!      - 30.05.2024 (MR): Fixed bug related to neutron emission if fragment was not in Sunet
!! .
!! @author C. Winteler


!> Read the fission distribution from a file
!!
!! The fission distribution is read from a file and stored in the
!! fragment_array. The default file contains the fission distribution
!! according to [Mumpower et al. (2020)](https://ui.adsabs.harvard.edu/abs/2020PhRvC.101e4607M/abstract).
!! However, the format has been modified compared to the original publication.
!! An example of the file looks like:
!! \file{
!! 93  220  574
!! 0 0 0
!!  019  048  1.96607e-06
!!  020  048  2.24289e-05
!!  020  049  1.88041e-05
!!  020  050  7.65944e-06
!! }
!! The first line contains the Z, A and number of the fissioning nucleus.
!! The next line is a dummy line. Then followed by Z, A and the yield Y(Z,A).
!! Note that \f$\sum Y(Z,A) \cdot A \f$ should be the mass number of the
!! parent nucleus. Furthermore,  \f$\sum Y(Z,A) = 2\f$ in case 2 fragments are created.
!! A large part of the subroutine deals with the problem what to do if the fragment
!! is not included in the network. In case of a nucleus heavier than the ones contained in
!! the network, the fragment is split into a lighter isotope plus neutrons.
!! For lighter nuclei where neutrons would be necessary to create a nucleus that is in the network,
!! the neutrons are "borrowed" from the heaviest fragment. This latter case should almost never happen.
!! If the remapping fails for some reason, an error will be raised.
!!
!! @see [Mumpower et al. (2020)](https://ui.adsabs.harvard.edu/abs/2020PhRvC.101e4607M/abstract).
!!
!! @author M. Reichert
!! @date 14.02.23


!> Fill the rates with the correct fragments
!!
!! This subroutine fills the rates with the correct fragments
!! from [Mumpower et al. (2020)](https://ui.adsabs.harvard.edu/abs/2020PhRvC.101e4607M/abstract).
!! This subroutine makes use of the fragtype struct.
!! If no fragment is found, the fragment distribution is set to the
!! one given by missing_frags.
!! For beta-delayed fission the fissioning nucleus is the one of (Z+1, A)
!! for neutron induced fission the nucleus with (Z, A+1), and for spontanous
!! fission (not used within fissflag = 3) it is (Z,A).
!!
!! @author M. Reichert
!! @date 14.02.2023


!> Calculates the (neutron-induced) fission fragment mass distribution according to
!! the ABLA07 model: Kelic, Ricciardi, & Schmidt (arXiv:0906.4193)
!!
!! @see [Kelic et al. 2009](https://ui.adsabs.harvard.edu/abs/2009arXiv0906.4193K/abstract)


!> Calculates the (beta-delayed and spontaneous) fission fragment mass distribution according to
!! the ABLA07 model: Kelic, Ricciardi, & Schmidt (arXiv:0906.4193)
!!
!! @see [Kelic et al. 2009](https://ui.adsabs.harvard.edu/abs/2009arXiv0906.4193K/abstract)


!>
!! @brief Network timestepping along the thermodynamic trajectory,
!! specified by {ztime, ztemp, zdens}[zsteps]
!!
!! This subroutine calls more specific subroutines to calculate the
!! timestep. This also depends on the conditions. For example, in NSE it
!! call \ref ye_timestep, while it calls \ref abchange_timestep otherwise.
!!
!! @note Gear solver will only be affected by the last call of this subroutine
!! of \ref restrict_timestep
!!
!! \b Edited:
!!    - OK: 13.01.14
!!    - OK:  7.11.16
!!    - OK: 27.08.17 - merged in the rest of timestepping subroutines
!!    - MR: 27.06.18 - introduced additional subroutine "restrict_timestep"
!! .


!>
!! @brief Restricting the previously selected timestep
!!
!! Possible restrictions are given by the termination criterion and
!! the trajectory datapoints as well as custom selected snapshots.
!! Furthermore, it is restricted to hit the NSE transition temperature
!! (\ref parameter_class::nsetemp_cold).
!!
!! @note The timestep of the gear solver, which is evolved independently in
!! \ref gear_module is also effected by this subroutine.
!!
!! \b Edited:
!!    - MR: 27.06.18
!!    - MR: 22.12.20  - Removed "const" parameter
!! .


!>
!! @brief Estimate the timestep from the change of electron fraction
!!
!! In NSE, only (slow) weak reactions are taken into account when calculating the
!! timestep. Therefore, only the change in \f$ y_e \f$ is considered here and
!! the timestep is usually larger than in the full network mode.
!! The timestep is calculated by:
!! \f[ h = h_\mathrm{old} \cdot \eta \frac{y_e}{|\Delta y_e|} \f]
!! with \f$ \eta \f$ being the parameter \ref parameter_class::timestep_factor.
!!
!! \b Created: OK 28.08.2017
!!


!>
!! @brief Estimate the timestep from the abundances change
!!
!! In the network evolution mode, the timestep is calculated based on the
!! most changing isotope. The timestep is the maximum of :
!! \f[ h = \eta \cdot \left|\frac{Y}{\Delta Y} \right|  \f]
!! for all nuclei above a certain threshold abundance
!! \ref parameter_class::timestep_Ymin. The factor \f$ \eta \f$ is determined
!! by the parameter \ref parameter_class::timestep_factor.
!!
!! \b Created: OK 28.08.2017
!!


!>
!! @brief Estimate the hydro timestep
!!
!! The timestep is restricted by the change of the hydrodynamic conditions
!! (i.e., temperature and density). The maximum change of them is determined
!! by the parameter \ref parameter_class::timestep_hydro_factor.
!! If the temperature or density change to rapidly the timestep will be decreased
!! and ultimately, if the timestep is lower than \f$ 10^{-24}s \f$ an exception
!! will be raised and the code terminates. The subroutine is also responsible
!! to update the next temperature (ttemp) and density (tdens) that are used
!! in \ref restrict_timestep.
!!
!! @note This subroutine restricts only the timestep for the implicit euler solver,
!! not for the gear solver.
!!
!! \b Created: OK 28.08.2017
!!


!>
!! Selects the timestep
!!
!! This subroutine is the main interface to the \ref driver.f90 .
!! It calls \ref timestep and initializes the timestep in case
!! of the first call.
!!
!! \b Edited:
!!      - 17.12.2016
!! .


!>
!! @brief Returns temperature, density, and radius for a given time "time_i".
!!
!! The time, entropy, and electron fraction are only inputs and are not changed.
!! The update depends on the trajectory mode of the run and can be either
!! interpolated from a trajectory, got from the expansion, or from an analytic
!! expression.
!!
!! \b Edited:
!!       - MR: 15.01.2020 - Moved it from advance_implicit_euler/gear to this new subroutine
!!       - MR: 10.02.2023 - Gave an optional output for the temperature
!! .


!>
!! Advance system to the next step for the implicit Euler method
!!
!! This subroutine solves one timestep for the implicit Euler method
!! via a newton-raphson (NR) scheme. The maximum amount of iterations for
!! the NR is controlled by the parameter \ref parameter_class::nr_maxcount.
!! The NR is successful if the mass conservation deviates less than
!! parameter_class::nr_tol. If the maximum iterations have been reached without
!! convergence, it repeats the calculation with half of the timestep.
!! This is done parameter_class::adapt_stepsize_maxcount many times. If after
!! this amount of iterations still no convergence could be achieved it will
!! raise an error.
!!
!! @see [Winteler 2013](https://edoc.unibas.ch/29895/)
!!
!! \b Edited:
!!     - OK: 15.06.2017 - Made into a separate subroutine
!!     - MR: 06.07.2022 - Let it crash if the result does not converge properly
!! .


!>
!! Advance system to the next step using the Gear method
!! (using \ref gear_module)
!!
!! This subroutine is similar to \ref advance_implicit_euler. However, no
!! additional check for convergence is done after the newton-raphson. This is
!! not necessary as the Gear solver has its estimate of a possible error
!! in the next step, given by evolving higher orders and comparing to lower ones.
!!
!! @see \ref gear_module, [Martin, D. 2017](https://tuprints.ulb.tu-darmstadt.de/6301/)
!!
!! \b Edited:
!!       -  DM 15.06.2017
!!       -  OK 27.08.2017
!!       -  MR 22.12.2020
!! .


!>
!! @brief Function to decide whether a character is a number or not (i.e., 0-9).
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = is_digit("5")
!! c = is_digit("a")
!!~~~~~~~~~~~~~~
!! b will be .True. and c will be .False.
!!
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Function to decide whether a character is a mathematical operator
!!        or not. Functions (as e.g., sin) are not defined here!
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = is_operator("+")
!! c = is_operator("5")
!!~~~~~~~~~~~~~~
!! b will be .True. and c will be .False.
!!
!! @see is_line_operator, is_power_operator, is_separator, is_dot_operator
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Function to decide whether a character is "*" or "/"
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = is_dot_operator("+")
!! c = is_dot_operator("*")
!!~~~~~~~~~~~~~~
!! b will be .False. and c will be .True.
!!
!! @see is_line_operator, is_power_operator, is_separator, is_operator
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Function to decide whether a character is a "+" or "-"
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = is_line_operator("+")
!! c = is_line_operator("*")
!!~~~~~~~~~~~~~~
!! b will be .True. and c will be .False.
!!
!! @see is_dot_operator, is_power_operator, is_separator, is_operator
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Function to decide whether a character is a "^"
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = is_power_operator("^")
!! c = is_power_operator("-")
!!~~~~~~~~~~~~~~
!! b will be .True. and c will be .False.
!!
!! @see is_dot_operator, is_line_operator, is_separator, is_operator
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Function to decide whether a character can be associated with a number.
!!
!! Allowed characters are ".", "d", and "e"
!! (for scientific format of a number).
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = is_separator(",")
!! c = is_separator("-")
!!~~~~~~~~~~~~~~
!! b will be .True. and c will be .False.
!!
!! @see is_dot_operator, is_line_operator, is_separator, is_operator, is_power_operator
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Function to perform a simple mathematical operation.
!!
!! Depending on the input character, the function performs
!! "+". "-", "*", "/", or "^". In case of a different character, an
!! error is raised.
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = operation(10.3, 2.7, "+")
!!~~~~~~~~~~~~~~
!! b will be 13.
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Function to perform a function operations.
!!
!! Depending on the input it will calculate,
!! e.g., the square root (sqrt) or the sinus (sin).
!! To add a function to the functionality of the parser,
!! add the translation in this function here.
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = eval_function(4, "sqrt")
!!~~~~~~~~~~~~~~
!! b will be 2.
!!
!! @note New parsing functions can be defined here.
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Subroutine to check the parsing string for consistency and correct it.
!!
!! This subroutine will convert all characters to lower case characters
!! (e.g., 4E-1 -> 4e-1) and will add a leading "0" in case the string starts
!! with a mathematical operator (i.e., + or -, e.g., "-3+5" -> "0-3+5").
!! Furthermore, it checks for "+-" (and "++", "--" and all combinations)
!! and will correct it to "-". Additionally "**" is corrected to "^",
!! in this way the  power can be written by both (**, and ^).
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! parsing_string = "-2+-3**2"
!! call make_pars_str_consistent()
!!~~~~~~~~~~~~~~
!! After this, parsing_string will be "0-2-3^2"
!!
!! @returns A corrected string that can be parsed by other functions
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Function to define constants.
!!
!! This function translates names of constants
!! to numbers (real). For example, "pi" is
!! translated to 3.1415. Define new constants
!! (names and values) in this function.
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = common_variables("pi")
!!~~~~~~~~~~~~~~
!! After this, will be 3.141592653589793
!!
!! @note New variables can be defined here.
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Store mathematical operators (+-*/) and numbers in arrays.
!!
!! The result of this subroutine are two arrays, one containing all
!! operators (e.g., for "3+2*2+1-1": ['+','*','+','-']) and one
!! array containing all numbers (as real type, [3,2,2,1,1]).
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! parsing_string = "0-2-3^2"
!! call store_digits_operator()
!!~~~~~~~~~~~~~~
!! After this, the array \ref operators will contain ("-","-","^"), and
!! the array \ref numbers will contain (0, 2, 3, 2).
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Evaluate a complex string expression.
!!
!! Evaluate expressions with brackets ( i.e., "(" and ")" ) and
!! function names (i.e., "sin(5)" ).
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! parsing_string = "2+sin(pi)-5*(1+1)"
!! call evaluate()
!!~~~~~~~~~~~~~~
!! After this, the array \ref numbers will have -8 on its first entry.
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Takes a string and evaluates the expression
!!
!! This function is accessible to the outside of the module.
!! It serves as interface between other modules and this one.
!! Also replaces \ref variable_name with \ref variable_value.
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! b = parse_string("-8+3*(2-1)-x",10)
!!~~~~~~~~~~~~~~
!! After this, b will be -15.
!!
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! @brief Finds a value of the variable for a given y-value
!!
!! This function solves an equation, i.e., finds the value of
!! variable "x" for expressions as, for example, "3*x+2+x^2 = 10"
!! returns 1.701562. This works with a newton raphson to find
!! the root of f(x) - 10.
!!
!! ### Example
!!~~~~~~~~~~~~~~.f90
!! input_string  = "3*x+2+x^2"
!! eq_value      = 10
!! initial_guess = 0.0
!! converged     = .False.
!! result        = 0.0
!! call find_start_value(input_string,eq_value,initial_guess,converged,result)
!!~~~~~~~~~~~~~~
!! After this, result will be 1.701562 and converged will be .True.
!!
!! @author  Moritz Reichert
!! @date    20.12.20


!>
!! Reads isotope names from file 'net_source' and saves them in net_names().
!! Returns number of isotopes in network.
!!
!! This function reads the sunet with the same format as the following example:
!! \file{
!!    n
!!    p
!!    d
!!    t
!!  he3
!!  he4
!!  he6
!!  li6
!!  li7
!!  li8
!!  li9
!! ...}
!!
!! \b Edited:
!!       - 11.01.14
!! .


!>
!! @brief Return a string to represent a given reaction
!!
!! This routine is useful for error messages in case
!! a rate is not working as intented.
!!
!! ### Example
!! For rrate(i) being the decay of ni56
!! ~~~~~~~~~~~.f90
!! a = reaction_string(rrate(i))
!! ~~~~~~~~~~~
!! will return a="ni56 => co56".
!!
!! @author Moritz Reichert


!>
!! Returns lowercase of input string. Numbers are not changed.
!!
!! ### Example:
!!~~~~~~~~~~~~.f90
!! a = 'Ti44'
!! call lowercase(a)
!! b = 'This Is A Text 123'
!! call lowercase(b)
!!~~~~~~~~~~~~
!! After this, a will be 'ti44' and b will be 'this is a text 123'
!!
!! @returns The lowercase of the input string
!!


!>
!! Converts isotope names of weak-table format to the ones in reaclib.
!!
!! ### Example:
!!~~~~~~~~~~~~.f90
!! a = '  h1'
!! call convert(a,b)
!! a = ' n01'
!! call convert(a,c)
!!~~~~~~~~~~~~
!! After this, b will be '   p' and c will be '   n'
!!
!! @returns Reaclib names of neutrons and protons for input "h1" or "n01"
!!
!! \b Edited:
!!       - 09.03.2017
!! .


!> Returns the index number of isotope 'name'
!!
!! \b Edited:
!!     - 11.01.14
!!     - 20.05.19
!! .


!> Read the general network information from a binary file
!!
!! This subroutine reads the information that is contained in
!! the winvn and sunet from a previously saved binary file.
!! This is necessary if the parameter \ref use_prepared_network
!! is set to .true. and the network is read from a prepared
!! network file.
!!
!! @author M. Reichert
!! @date 21.07.23


!> Save the general network information to a binary file
!!
!! This subroutine saves the information that is contained in
!! the winvn and sunet. This is necessary if the code is
!! run in network preparation mode for the parameter
!! \ref use_prepared_network .
!!
!! @author M. Reichert
!! @date 21.07.23


!>
!! Reads nuclear properties (name,a,n,z,spin,mass excess,partition functions)
!! from file 'winvn' and htpf file and writes them into isotope(:).
!! Also the arrays of the partition function grid and temperature grid are
!! initialized here.
!!
!! \b Edited:
!!      - 11.01.14
!!      - 11.02.21 - MR: Implemented a switch for htpf functions and
!!                       moved things to additional subroutine
!! .


!>
!! Reads nuclear properties (name,a,n,z,spin,mass excess,partition functions)
!! from file 'winvn' and writes them into isotope(:).
!! An example entry of a winvn can look like:
!! \l_file{
!! ne33      33.000  10  23   1.5    45.997 reac1
!!  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0
!!  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0  1.00000E+0  1.01000E+0
!!  1.01000E+0  1.02000E+0  1.03000E+0  1.07000E+0  1.12000E+0  1.19000E+0  1.28000E+0  1.40000E+0
!! ...}
!!
!! \b Edited:
!!    - 11.02.21 - MR: Moved it from get_nuclear_properties to this subroutine
!! .


!>
!! Checks if sunet file contains valid isotope names
!!
!! \b Edited:
!!        - 11.01.14
!! .


!>
!! Read the file with high-temperature partition function
!! (normally datafile2.dat). An example of the file may look like:
!!
!! \l_file{
!! Title: Nuclear Partition Functions at Temperatures Exceeding 10^10^ K
!! Author: Rauscher T.
!! Table: Renormalized partition functions G(T_9_) including high temperature
!!        corrections. The values given here were calculated with level densities
!!        based on FRDM input (see text).
!! \================================================================================
!! Byte-by-byte Description of file: datafile2.txt
!! \--------------------------------------------------------------------------------
!!    Bytes Format Units Label  Explanations
!! \--------------------------------------------------------------------------------
!!    1-  5 A5     ---   Name   Nuclide name
!!    7-  8 I2     ---   Z      Charge number of nuclide
!!   10- 12 I3     ---   A      Mass number of nuclide
!!   15- 17 F3.1   ---   J0     Ground-state spin of nuclide
!!   19- 27 E9.2   ---   G12    Renormalized partition function for T = 12E9
!!   ....
!!   o13    8  13  1.5 1.00E+000 1.00E+000 9.99E-001 9.95E-001 9.90E-001 9.84E-001 9.76E-001 9.68E-001 9.59E-001 ...
!! ...}
!!
!! \b Edited: 11.01.14


!>
!! Finds an isotope index in the network table, given its A and Z.
!! In case it was not found, -1 is returned.
!!
!!
!! \b Edited: 11.01.14


!> Read a file with neutrino loss energy.
!!
!! This file contains the neutrino loss energy for the beta decays in the network.
!! The information is used in case nuclear heating is turned on.
!! An example of the file could look like this:
!! \file{...
!! al34     4.803857E+00
!! al35     6.072946E+00
!! al37     5.639200E+00
!! si25     4.794861E+00
!! si26     1.968612E+00
!! si27     2.070827E+00
!! si31     8.963707E-01
!! si32     1.581000E-01
!! si34     1.778200E+00
!! si35     3.314272E+00
!! si36     3.432230E+00
!! si38     3.446900E+00
!!... }
!! The first column is the isotope name, the second column is the average neutrino loss
!! energy in MeV.
!!
!! @author Moritz Reichert
!! @date   31.03.2023


!>
!! Identifies the nuclide names and indices corresponding to z,n combinations
!! (z1,n1), (z2,n2).
!!
!! If any of the two nuclides is not part of the network,
!! err=1 and all other properties are set to 0 or "    " respectively.
!!
!!
!! \b Edited:
!!       - 12.01.14
!!       - 23.01.21, MR - moved it to benam_class
!! .


!> Count and read reaclib reactions
!!
!! This subroutine will fill \ref nrea with the amount
!! of reaclib reactions and the \ref rrate_reaclib array
!! with reaction rates from a reaclib file.
!!
!! @author M. Reichert
!! @date 25.01.21


!> Read the complete rrate array from a binary file
!!
!! This subroutine reads the complete rrate array from a binary file.
!! The binary file has to be created beforehand. If the binary data is read,
!! no other data has to be read
!!
!! @author M. Reichert
!! @date 21.07.23


!> Save the complete rrate array to a binary file
!!
!! This subroutine saves the complete rrate array to a binary file.
!!
!! @author M. Reichert
!! @date 21.07.23


!> Calculate a reaclib rate.
!!
!! The rate is calculated according to the reaclib fit function:
!! \f[ \lambda = \exp\left[ a_0 + \sum_{i=1}^5 a_i T_9^{(2i-5)/3} +a_6 \log T_9 \right]  \f]
!!
!! @see nucstuff_class::calc_t9_pow
!!
!! \b Edited:
!!      - 26.07.22, MR: created this subroutine from code parts in jacobian_class.
!! .


!> Merge the reaclib rates into a larger array
!!
!! The subroutine combines a larger rate array with
!! \ref rrate_reaclib. Afterwards it deallocates \ref rrate_reaclib.
!!
!! @returns Large rate array with new size, containing the reaclib reactions
!!
!! @author M. Reichert
!! @date 25.01.21


!> Read reaclib reaction rates
!!
!! This routine reads the reaclib file and stores
!! the reactions into \ref rrate_reaclib. An example file
!! looks like:
!! \file{...
!!       li9  be9                            wc12w     1.36060e+01
!! 6.501820e-01 0.000000e+00 0.000000e+00 0.000000e+00
!! 0.000000e+00 0.000000e+00 0.000000e+00
!!      li11 be11                            wc12w     2.05510e+01
!! 2.322150e+00 0.000000e+00 0.000000e+00 0.000000e+00
!! 0.000000e+00 0.000000e+00 0.000000e+00
!! ...}
!!
!! @see [Reaclib file format](https://reaclib.jinaweb.org/help.php?topic=reaclib_format&intCurrentNum=0)
!!
!! \b Edited:
!!     - 25.01.21, MR - Moved it from network_init to this subroutine
!!     - 28.07.22, MR - Introduced new chapters
!! .


!> Count the amount of reaclib reactions
!!
!! After the subroutine has been called
!! \ref nrea will store the amount of reaclib reaction rates.
!!
!! \b Edited:
!!    - 25.01.21, MR - Moved this routine from network_init_module to this new subroutine
!! .


!> The integrand in effective psi, eq.[16] of Langanke & Pinedo (2001)


!>
!! Initialize the expansion module and open files for debugging.
!!
!! This subroutine also determines if the simulation
!! has to use the expansion routine or not (depending
!! on parameter_class::termination_criterion).
!!
!! @author: Moritz Reichert
!!
!! \b Edited:
!!         - 28.02.17
!!         - MR 22.12.20
!!         - MR 22.01.21
!! .


!>
!! Calculates the velocity for trajectory extrapolation by linear regression
!! on a few last points; the number of points is controlled by the parameter
!! parameter_class::extrapolation_width.
!!
!! @remark At verbose Level >2 this creates a file called "debug_vel.dat"
!!         which lists extrapolated points and the computed value of velocity.
!!
!! \b Edited:
!!       - 09.03.17
!!       - OK 13.01.2014
!!       - OK 17.06.2017 - cleanup, renamed: variance -> residual_expansion
!!       - MR 22.01.2021 - Changed entropy calculation
!! .


!>
!! Returns temperature, radius, density, and entropy after the trajectory has ended.
!!
!! This depends on the \ref parameter_class::expansiontype parameter.
!! Possible values are:
!!

!!
Expansiontype parameter

!!
 Value      Expansion                           Literature
!!
 1          Adiabatic expansion                 [Korobkin et al. 2012](https://ui.adsabs.harvard.edu/abs/2012MNRAS.426.1940K/abstract)
!!
 2          Exponential expansion               -
!!
 3          Expansion with const. velocity      -
!!
 4          Expansion with const. velocity      [Fujimoto et al. 2008](https://ui.adsabs.harvard.edu/abs/2008ApJ...680.1350F/abstract)
!!

!!
!! \b Edited:
!!     - 26.01.21 - MR
!!     - 17.02.21 - MR: Cleaned up the routine and removed some expansion types
!! .


!>
!! Close debug files of the module
!!
!! @author: Moritz Reichert
!!
!! \b Edited:
!!    - 28.02.17
!! .


!> @brief Initializes the thermal_neutrino_module.
!!
!! This subroutine is called in the initialization of the code.
!! It only contains debug statements.
!!
!! @author M. Reichert
!! @date   12.04.2023


!> @brief Calculates the neutrino emissivity.
!!
!! This subroutine is an interface to the subroutine
!! sneut5_aa from the sneut5.f90 file.
!! It calculates the neutrino emissivity and its derivatives
!! with respect to temperature, density, average mass number and
!! average atomic number.
!! The derivatives are not used in the current version of the code.
!! The file sneut5.f90 is based on the fit of
!! [Itoh et al. 1996](https://ui.adsabs.harvard.edu/abs/1996ApJS..102..411I/abstract)
!! accessed via [Cococubed](https://cococubed.com/code_pages/nuloss.shtml).
!!
!! @author M. Reichert
!! @date   12.04.2023


!
! file contains fermi function routines:
!
! function zfermim12 does a rational function fit for the order -1/2 integral
! function zfermi12 does a rational function fit for the order 1/2 integral
! function zfermi1 does a rational function fit for the order 1 integral
! function zfermi32 does a rational function fit for the order 3/2 integral
! function zfermi2 does a rational function fit for the order 2 integral
! function zfermi52 does a rational function fit for the order 5/2 integral
! function zfermi3 does a rational function fit for the order 3 integral
!
! function ifermim12 is a rational function fit for the inverse of order -1/2
! function ifermi12 is a rational function fit for the inverse of order 1/2
! function ifermi32 is a rational function fit for the inverse of order 3/2
! function ifermi52 is a rational function fit for the inverse of order 5/2


!> Further information:
!! http://netlib.org/quadpack/index.html
!! https://orion.math.iastate.edu/burkardt/f_src/quadpack/quadpack.html
!
!******************************************************************************
!
! 1. introduction
!
!    quadpack is a fortran subroutine package for the numerical
!    computation of definite ond-dimensional integrals. it originated
!    from a joint project of r. piessens and e. de doncker (appl.
!    math. and progr. div.- k.u.leuven, belgium), c. ueberhuber (inst.
!    fuer math.- techn.u.wien, austria), and d. kahaner (nation. bur.
!    of standards- washington d.c., u.s.a.).
!
! 2. survey
!
!    - qags : is an integrator based on globally adaptive interval
!             subdivision in connection with extrapolation (de doncker,
!             1978) by the epsilon algorithm (wynn, 1956).
!
!    - qagp : serves the same purposes as qags, but also allows
!             for eventual user-supplied information, i.e. the
!             abscissae of internal singularities, discontinuities
!             and other difficulties of the integrand function.
!             the algorithm is a modification of that in qags.
!
!    - qagi : handles integration over infinite intervals. the
!             infinite range is mapped onto a finite interval and
!             then the same strategy as in qags is applied.
!
!    - qawo : is a routine for the integration of cos(omega*x)*f(x)
!             or sin(omega*x)*f(x) over a finite interval (a,b).
!             omega is is specified by the user
!             the rule evaluation component is based on the
!             modified clenshaw-curtis technique.
!             an adaptive subdivision scheme is used connected with
!             an extrapolation procedure, which is a modification
!             of that in qags and provides the possibility to deal
!             even with singularities in f.
!
!    - qawf : calculates the fourier cosine or fourier sine
!             transform of f(x), for user-supplied interval (a,
!             infinity), omega, and f. the procedure of qawo is
!             used on successive finite intervals, and convergence
!             acceleration by means of the epsilon algorithm (wynn,
!             1956) is applied to the series of the integral
!             contributions.
!
!    - qaws : integrates w(x)*f(x) over (a,b) with a < b finite,
!             and   w(x) = ((x-a)**alfa)*((b-x)**beta)*v(x)
!             where v(x) = 1 or log(x-a) or log(b-x)
!                            or log(x-a)*log(b-x)
!             and   alfa > (-1), beta > (-1).
!             the user specifies a, b, alfa, beta and the type of
!             the function v.
!             a globally adaptive subdivision strategy is applied,
!             with modified clenshaw-curtis integration on the
!             subintervals which contain a or b.
!
!    - qawc : computes the cauchy principal value of f(x)/(x-c)
!             over a finite interval (a,b) and for
!             user-determined c.
!             the strategy is globally adaptive, and modified
!             clenshaw-curtis integration is used on the subranges
!             which contain the point x = c.
!
!  each of the routines above also has a "more detailed" version
!    with a name ending in e, as qage.  these provide more
!    information and control than the easier versions.
!
!
!   the preceeding routines are all automatic.  that is, the user
!      inputs his problem and an error tolerance.  the routine
!      attempts to perform the integration to within the requested
!      absolute or relative error.
!   there are, in addition, a number of non-automatic integrators.
!      these are most useful when the problem is such that the
!      user knows that a fixed rule will provide the accuracy
!      required.  typically they return an error estimate but make
!      no attempt to satisfy any particular input error request.
!
!      qk15
!      qk21
!      qk31
!      qk41
!      qk51
!      qk61
!           estimate the integral on [a,b] using 15, 21,..., 61
!           point rule and return an error estimate.
!      qk15i 15 point rule for (semi)infinite interval.
!      qk15w 15 point rule for special singular weight functions.
!      qc25c 25 point rule for cauchy principal values
!      qc25o 25 point rule for sin/cos integrand.
!      qmomo integrates k-th degree chebychev polynomial times
!            function with various explicit singularities.
!
! 3. guidelines for the use of quadpack
!
!    here it is not our purpose to investigate the question when
!    automatic quadrature should be used. we shall rather attempt
!    to help the user who already made the decision to use quadpack,
!    with selecting an appropriate routine or a combination of
!    several routines for handling his problem.
!
!    for both quadrature over finite and over infinite intervals,
!    one of the first questions to be answered by the user is
!    related to the amount of computer time he wants to spend,
!    versus his -own- time which would be needed, for example, for
!    manual subdivision of the interval or other analytic
!    manipulations.
!
!    (1) the user may not care about computer time, or not be
!        willing to do any analysis of the problem. especially when
!        only one or a few integrals must be calculated, this attitude
!        can be perfectly reasonable. in this case it is clear that
!        either the most sophisticated of the routines for finite
!        intervals, qags, must be used, or its analogue for infinite
!        intervals, qagi. these routines are able to cope with
!        rather difficult, even with improper integrals.
!        this way of proceeding may be expensive. but the integrator
!        is supposed to give you an answer in return, with additional
!        information in the case of a failure, through its error
!        estimate and flag. yet it must be stressed that the programs
!        cannot be totally reliable.
!
!    (2) the user may want to examine the integrand function.
!        if bad local difficulties occur, such as a discontinuity, a
!        singularity, derivative singularity or high peak at one or
!        more points within the interval, the first advice is to
!        split up the interval at these points. the integrand must
!        then be examinated over each of the subintervals separately,
!        so that a suitable integrator can be selected for each of
!        them. if this yields problems involving relative accuracies
!        to be imposed on -finitd- subintervals, one can make use of
!        qagp, which must be provided with the positions of the local
!        difficulties. however, if strong singularities are present
!        and a high accuracy is requested, application of qags on the
!        subintervals may yield a better result.
!
!        for quadrature over finite intervals we thus dispose of qags
!        and
!        - qng for well-behaved integrands,
!        - qag for functions with an oscillating behavior of a non
!          specific type,
!        - qawo for functions, eventually singular, containing a
!          factor cos(omega*x) or sin(omega*x) where omega is known,
!        - qaws for integrands with algebraico-logarithmic end point
!          singularities of known type,
!        - qawc for cauchy principal values.
!
!        remark
!
!        on return, the work arrays in the argument lists of the
!        adaptive integrators contain information about the interval
!        subdivision process and hence about the integrand behavior:
!        the end points of the subintervals, the local integral
!        contributions and error estimates, and eventually other
!        characteristics. for this reason, and because of its simple
!        globally adaptive nature, the routine qag in particular is
!        well-suited for integrand examination. difficult spots can
!        be located by investigating the error estimates on the
!        subintervals.
!
!        for infinite intervals we provide only one general-purpose
!        routine, qagi. it is based on the qags algorithm applied
!        after a transformation of the original interval into (0,1).
!        yet it may eventuate that another type of transformation is
!        more appropriate, or one might prefer to break up the
!        original interval and use qagi only on the infinite part
!        and so on. these kinds of actions suggest a combined use of
!        different quadpack integrators. note that, when the only
!        difficulty is an integrand singularity at the finite
!        integration limit, it will in general not be necessary to
!        break up the interval, as qagi deals with several types of
!        singularity at the boundary point of the integration range.
!        it also handles slowly convergent improper integrals, on
!        the condition that the integrand does not oscillate over
!        the entire infinite interval. if it does we would advise
!        to sum succeeding positive and negative contributions to
!        the integral -e.g. integrate between the zeros- with one
!        or more of the finitd-range integrators, and apply
!        convergence acceleration eventually by means of quadpack
!        subroutine qelg which implements the epsilon algorithm.
!        such quadrature problems include the fourier transform as
!        a special case. yet for the latter we have an automatic
!        integrator available, qawf.
!


!! Allocate and construct a new ATS object
!! Returns a pointer to new ATS object


!! Destroy ATS object


!! Setup ATS for LSM simulation


!! Initialize ATS for this simulation


!! Advance ATS by dt


!! WIP
!! Sets ATS coupling variables infiltration, evaporation, and transpiration


!subroutine nf90_handle_err(status, errmsg)
!  integer,          intent(in) :: status
!  character(len=*), intent(in) :: errmsg
!
!    if(status /= nf90_noerr) then
!      print *, trim(nf90_strerror(status))//" : "//trim(errmsg)
!      Stop
!    end if
!  end subroutine nf90_handle_err


! (c) 2008, Lawrence Livermore National Security Limited Liability Corporation.
! All rights reserved.
!
! Redistribution and use in source and binary forms, with or without modification, are permitted
! provided that the following conditions are met:
!
!     * Redistributions of source code must retain the above copyright notice, this list
!       of conditions and the following disclaimer.
!     * Redistributions in binary form must reproduce the above copyright notice, this list
!       of conditions and the following disclaimer in the documentation and/or other materials
!       provided with the distribution.
!     * Neither the name of the Lawrence Livermore National Security Limited Liability Corporation
!       nor the names of its contributors may be used to endorse or promote products derived from
!       this software without specific prior written permission.
!
! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
! IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
! CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
! IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
! OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


! A "packed" identity vector analog of identity matrix.


!Open output files


!Close output files


!Generate an array of n numbers sampled from a Gaussian normal distribution with mean and standard deviation given.
!Adapted from RosettaCode.org.


!Generate a scalar sampled from a Gaussian normal distribution with mean and standard deviation given.
!Adapted from RosettaCode.org.


!Generate a random seed based on the clock time.
!Adapted from GNU site.


!Generate a random seed based on the clock time --- For use in parallel.


!Subroutine to shuffle an array by Knuth Shuffle.
!Inspired by RosettaCode.org.


!Subroutine that takes two sets, shuffles them together n times, then divides them along the columns, returning same sized arrays that are a mix of both sets.


!Function to make a cluster of "n" points centered at "center" with given std "sigma."


!Procedures for Kahan summation objects
!Algorithm for Kahan summation


!Write the cosmo observables headers to file


!Print the cosmo observables to file


!_______________________________________________________________________
! The modified SLATEC error handling routines begin here.


!_______________________________________________________________________
! Beginning of Jacobian related routines that use MA28


! End of DVODE_F90 subroutines
!_______________________________________________________________________
! Beginning of LINPACK and BLAS subroutines


!_______________________________________________________________________
! Private Variable Information.
! LP, MP are used by the subroutine as the unit numbers for its warning
!     and diagnostic messages. Default value for both is 6 (for line
!     printer output). The user can either reset them to a different
!     stream number or suppress the output by setting them to zero.
!     While LP directs the output of error diagnostics from the
!     principal subroutines and internally called subroutines, MP
!     controls only the output of a message which warns the user that
!     he has input two or more non-zeros A(I),. .,A(K) with the same
!     row and column indices. The action taken in this case is to
!     proceed using a numerical value of A(I)+...+A(K). In the absence
!     of other errors, IFLAG will equal -14 on exit.
! LBLOCK Is a logical variable which controls an option of first
!     preordering the matrix to block lower triangular form (using
!     Harwell subroutine MC23A). The preordering is performed if LBLOCK
!     is equal to its default value of .TRUE. If LBLOCK is set to
!     .FALSE., the option is not invoked and the space allocated to
!     IKEEP can be reduced to 4*N+1.
! GROW is a logical variable. If it is left at its default value of
!     .TRUE., then on return from MA28AD or MA28BD, W(1) will give
!     an estimate (an upper bound) of the increase in size of elements
!     encountered during the decomposition. If the matrix is well
!     scaled, then a high value for W(1), relative to the largest entry
!     in the input matrix, indicates that the LU decomposition may be
!     inaccurate and the user should be wary of his results and perhaps
!     increase U for subsequent runs. We would like to emphasise that
!     this value only relates to the accuracy of our LU decomposition
!     and gives no indication as to the singularity of the matrix or the
!     accuracy of the solution. This upper bound can be a significant
!     overestimate particularly if the matrix is badly scaled. If an
!     accurate value for the growth is required, LBIG(Q.V.) should be
!     set to .TRUE.
! EPS, RMIN If, on entry to MA28BD, EPS is less than one, then RMIN
!     will give the smallest ratio of the pivot to the largest element
!     in the corresponding row of the upper triangular factor thus
!     monitoring the stability of successive factorizations. If RMIN
!     becomes very large and W(1) from MA28BD is also very large, it
!     may be advisable to perform a new decomposition using MA28AD.
! RESID Variable which on exit from MA30CD gives the value of the
!     maximum residual over all the equations unsatisfied because
!     of dependency (zero pivots).
! IRNCP, ICNCP Variables which monitor the adequacy of "elbow room"
!     in IRN and A/ICN, respectively. If either is quite large (say
!     greater than N/10), it will probably pay to increase the size of
!     the corresponding array for subsequent runs. If either is very low
!     or zero, then one can perhaps save storage by reducing the size of
!     the corresponding array.
! MINIRN, MINICN Integer variables which, in the event of a successful
!     return (IFLAG >= 0 or IFLAG = -14) give the minimum size of IRN
!     and A/ICN, respectively which would enable a successful run on
!     an identical matrix. On an exit with IFLAG equal to -5, MINICN
!     gives the minimum value of ICN for success on subsequent runs on
!     an identical matrix. In the event of failure with IFLAG = -6,-4,
!     -3,-2, OR -1, then MINICN and MINIRN give the minimum value of
!     LICN and LIRN, respectively which would be required for a
!     successful decomposition up to the point at which the failure
!     occurred.
! IRANK Integer variable which gives an upper bound on the rank of
!     the matrix.
! ABORT1 is a logical variable with default value .TRUE. If ABORT1 is
!     set to .FALSE., then MA28AD will decompose structurally singular
!     matrices (including rectangular ones).
! ABORT2 is a logical variable with default value .TRUE. If ABORT2 is
!     set to .FALSE., then MA28AD will decompose numerically singular
!     matrices.
! IDISP is an integer array of length 2. On output from MA28AD, The
!     indices of the diagonal blocks of the factors lie in positions
!     IDISP(1) to IDISP(2) of A/ICN. This array must be preserved
!     between a call to MA28AD and subsequent calls to MA28BD,
!     MA30CD or MA28ID.
! TOL If set to a positive value, then any non-zero whose modulus is
!     less than TOL will be dropped from the factorization. The
!     factorization will then require less storage but will be
!     inaccurate. After a run of MA28AD with TOL positive it is not
!     possible to use MA28BD and the user is recommended to use
!     MA28ID to obtain the solution. The default value for TOL is 0.0.
! THEMAX On exit from MA28AD, THEMAX will hold the largest entry of
!     the original matrix.
! BIG If LBIG has been set to .TRUE., BIG will hold the largest entry
!     encountered during the factorization by MA28AD or MA28BD.
! DXMAX On exit from MA28ID, DXMAX will be set to the largest component
!     of the solution.
! ERRMAX If MAXIT is positive, ERRMAX will be set to the largest
!     component in the estimate of the error.
! DRES On exit from MA28ID, if MAXIT is positive, DRES will be set to
!     the largest component of the residual.
! CGCE Used by MA28ID to check the convergence rate. If the ratio of
!     successive corrections is not less than CGCE, then we terminate
!     since the convergence rate is adjudged too slow.
! NDROP If TOL has been set positive on exit from MA28AD, NDROP will
!     hold the number of entries dropped from the data structure.
! MAXIT Maximum number of iterations performed by MA28ID. Default = 16.
! NOITER Set by MA28ID to the number of iterative refinement iterations
!     actually used.
! NSRCH If NSRCH is set to a value less than N, then a different pivot
!     option will be employed by MA28AD. This may result in different
!     fill-in and execution time for MA28AD. If NSRCH is less than or
!     equal to N, the workspace array IW can be reduced in length. The
!     default value for NSRCH is 32768.
! ISTART If ISTART is set to a value other than zero, then the user
!     must supply an estimate of the solution to MA28ID. The default
!     value for istart is zero.
! LBIG If LBIG is set to .TRUE., the value of the largest element
!     encountered in the factorization by MA28AD or MA28BD is returned
!     in BIG. Setting LBIG to .TRUE. will increase the time for MA28AD
!     marginally and that for MA28BD by about 20%. The default value
!     for LBIG is .FALSE.
!_______________________________________________________________________


! End of  MA28 subroutines.
!_______________________________________________________________________
! Beginning of JACSP routines.
! Change Record:
! ST 09-01-05
!   Convert to F90 using Metcalf converter
!   Trim trailing blanks using trimem.pl
!   Convert arithmetic operators to F90
!   Replace R1MACH by EPSILON
!   Run through nag tools suite
! ST 09-17-05
!   Delete RDUM and IDUM
!   Change FCN argument list
! ST 09-18-05
!   Add subroutine DGROUPDS to define the IGP and JGP arrays for JACSP
! ST 09-20-05
!   Modify JACSP to produce JACSPDB for sparse, dense, and
!   banded Jacobians
!_______________________________________________________________________


!Needs "result" because array-valued and recursive.


!Only used to get the 3rd order SR parameters for the SR approximation
!of the scalar running, alpha_s


! Powerspectrum for psi ptbs mode matrix, outputting full IJ matrix,
!adiabatic P(k), and isocurv P(k); includes cross correlations


!Basis perpend to adiab direction.  Gram-Schmidt


!Takes a vector and sets to zero those elements that are so small they're
!not affecting the normalization
!If there's a major hierarchy in scales for the vector components, then
!there can be a spurious component of the isocurvature direction
!oriented along the adiabatic one.  When you're approaching the
!adiabatic limit this can be the dominant contribution, so we force the
!smallest term to be zero whenever adding it doesn't affect the value of
!the norm.


!Projection of v orthogonally onto line spanned by u


!Norm of v


!Calc bundle exp_scalar by integrating tr(d2Vdphi2) to efold by Riemann sum


!Checks to see if H^2=V/(3-eps) is stable, ie, if H>0 and if V~0, then it will
!return FALSE for unstable.


!Require the background ICs to start with the same energy.
!Alternates selecting the fields and vels
!Assumes canonical kinetic term


!Uniform sampling of fields, unconstrained
!Also grabs momenta uniformly


!Find min of potential w/all but one param constrained by method of
!gradient descent.
!---Model dependent---
!Can put in an analytical soln to this problem here, rather than
!relying on gradient descent


!For a sum-separable potential only
!Set IC for each field at an equal displacement from the local minimum
!as measured by energy


!Chooses masses from flat/log priors


!Place priors on the terms in expansion of the cos term into
! 0.5*m^2phi^2 - (1/24)*alpha^2*phi^4


!Sets the masses in N-quadratic inflation according to hep-th/0512102
!Easther-McAllister
!........


!--------------------------------------------------------------------
!   marchenko-pastur distribution, with modification to exclude delta
!   -fn at origin. (Multiplied by beta)


!---------------------------------------------------------
!
!     a quick and dirty bisection rountine.
!


!**********************************************************
!Heapsorts an array based on the first column only.
!Adapted from Numerical Recipes pg 231.


!this subroutine makes a vector (of rank equal to the number of columns in table) equal to the ith row in a table.


!this subroutine changes the ith row of a table to equal the jth row.


!Newton's method for finding zeros to f(x)=0.
!Modified from: http://faculty.washington.edu/rjl/classes/am583s2013/notes/fortran_newton.html


!Given array XX and a value X, returns value XOUT st X is between XX(XOUT)
!and XX(XOUT+1)


!Find first entry in array that is (1) less than x and (2) the next entry is greater
!than x


! Polynomial interpolation
! Given array XA and YA (of same length) and given a value X, returns
!value Y such that if P(x) is a polynomial st P(XA_i)=YA_i, then Y=P(X) ---
!and an error estimate DY


!MULTIFIELD
!Scalar interpolating function with vector argument


!Integrates a one-dimensional real function from x0 to xend using
!the trapezoid rule with given number of steps


!Build a histogram over an N-dimensional real dataset


!Function to determine the binsize for an N-dimensional histogram


!Makes a grid of points between data_max and data_min where there are
!(numb_bins) of bins of size binsize


!Simple arithmetic mean


! csv_next_record --
!     Go to the next record (convenience routine)
! Arguments:
!     lun        LU-number of the CSV-file
! Result:
!     The current record is closed, the next write will be to the
!     new record
! Note:
!     This is a convenience routine, it may result in a superfluous
!     comma at the end of the previous record. This does not seem to
!     be problematic, though, for MS Excel
!


! csv_write_integer/real/dble --
!     Write a single integer/real/double precision real to the CSV-file
! Arguments:
!     lun        LU-number of the CSV-file
!     value      Value to write
!     advance    Advance (.true.) or not, so that more items can be
!                written to the same record
! Result:
!     The value is written to the current record of the CSV-file
!


! csv_write_char --
!     Write a single character string to the CSV-file
! Arguments:
!     lun        LU-number of the CSV-file
!     value      Value to write
!     advance    Advance (.true.) or not, so that more items can be
!                written to the same record
! Result:
!     The value is written to the current record of the CSV-file
!


! csv_write_integer/real/dble_1d --
!     Write a one-dimensional array of items to the CSV-file
! Arguments:
!     lun        LU-number of the CSV-file
!     array      Array to write
!     advance    Advance (.true.) or not, so that more items can be
!                written to the same record
! Result:
!     The array is written to the current record of the CSV-file
! Note:
!     Because the four routines of this type differ only in
!     the data type, we use an include file for the body.
!


! csv_write_integer/real/dble_2d --
!     Write a two-dimensional array of items to the CSV-file
! Arguments:
!     lun        LU-number of the CSV-file
!     array      Array to write
! Result:
!     The array is written to the current record of the CSV-file
! Note:
!     Because the four routines of this type differ only in
!     the data type, we use an include file for the body.
!


!Evalutes adiabatic power spectrum under SR approximation at field positions
!phi_end, given that the mode of interest crossed the horizon at phi_pivot
!Assumes a massless, uncorrelated mode subhorizon


!Assumes independent, GRFs at horizon exit


!Assumes independent, GRFs at horizon exit
!From Eq 41 in astro-ph/0611075


!Deriv of N wrt phi on horiz cross surface
!Battefeld-Easther eq 29


!2nd Deriv of N wrt phi on horiz cross surface
!Battefeld-Easther eq 32


!The function Z_i from Battefeld-Easther that encodes all details from the
!end of inflation surface.  Eq. 31


!Deriv of Z_i wrt fields at horiz cross
!Battefeld-Easther Eq. 33


!For a sum-separable potential V=\sum_i V_i.  This returns only the V_i part


!Subroutines for regularizing a 0/0 error in the summations above


!Code-related warnings handled here.


!Calculate observables, optionally grab a new IC or a new set of parameters
!each time this routine is called.


!Calculate observables for the power spectrum, as well as fNL, using the
!delta-N formalism in slow-roll


!Wrapper for using the bderivs with the dvode_f90_m integrator


!Wrapper for using the mode derivs with the dvode_f90_m integrator


!Wrapper for using the qderivs with the dvode_f90_m integrator


!Background derivatives y'=f(y)


! Full y (back+mode matrix+tensor) derivatives y'=f(y)


! Only works for square matrices


! Full y (back+mode matrix(in Q at horizon cross)+tensor) derivatives y'=f(y)


! Take a "hacked" vector, i.e., a matrix B that is in the
!form of a vector where the rows of B(i,1:N) --> first N terms in B(1:N), etc
!Returns the matrix form. NB: the vector must be a representation of a square
!matrix.


! Take a matrix and "hack" it into a vector, i.e.,
!a vector where the rows of B(i,1:N) --> first N terms in B(1:N), etc


!  (C) Copr. 1986-92 Numerical Recipes Software, adapted.


! Only called for ptb mode eqns


!Uses t as integration variable, copy of odeint_r --- only to be used with
!background


!When not requiring inflation to end, the stopping requirements will likely
!vary with the potential that you're using, so here's the function that you
!will need to edit.


!#####################################################################
!--- open grid file and store grid info


!#####################################################################
!--- read source grid and source data from src_file


!#####################################################################
!--- write remapped data to file dest_file


!--- initialization routine, reading namelist, read river source
!--- data and land grid information.


!#####################################################################
!--- remap data from src grid to destination grid.


!#######################################################################
! <SUBROUTINE NAME="atmos_grid_init" >
!   <OVERVIEW>
!    Initialization routine.
!   </OVERVIEW>
!   <DESCRIPTION>
!    Read namelist, write out version and namelist informaiton.
!   </DESCRIPTION>
!   <TEMPLATE>
!     call atmos_grid_init ( )
!   </TEMPLATE>
! </SUBROUTINE>


!#####################################################################
! --- read the namelist and write the version information to logfile. Also
! --- write the namelist to standard output


!#######################################################################
! <SUBROUTINE NAME="hgrid_init" >
!   <OVERVIEW>
!    Initialization routine.
!   </OVERVIEW>
!   <DESCRIPTION>
!    Read namelist, write out version and namelist informaiton, generate longitude
!     and latitude resolution.
!   </DESCRIPTION>
!   <TEMPLATE>
!     call hgrid_init ( )
!   </TEMPLATE>
! </SUBROUTINE>


!#######################################################################
!<SUBROUTINE NAME="topog_init">
!   <OVERVIEW>
!    Initialization routine.
!   </OVERVIEW>
!
!<DESCRIPTION>
!   Read topography namelist.
!</DESCRIPTION>
!   <TEMPLATE>
!     call topog_init(Topog, Hgrid)
!   </TEMPLATE>
!<IN NAME="Hgrid" TYPE="type(hgrid_data_type)">
!   A derived-type variable that contains horizontal grid information.
!</IN>
!<INOUT NAME="Topog" TYPE="type(topog_data_type)">
!   A derived-type variable that contains topography.
!</INOUT>
!</SUBROUTINE>