Working with Rate Objects#

List membership#

The Rate class defines an equality operator __eq__ that is used as follows:

  • To test equality of rates, for example, given a Rate r and a list of rates rate_list doing:

    if r in rate_list:
        # do something
    

    will use Rate.__eq__ for the comparison.

  • For a RateCollection, we use lists for RateCollection.rates and RateCollection.all_rates. As noted above, to test membership in a list, the equality operator will be used.

Hashing and equality#

Rates can also be dictionary keys or set members. Their hashes use the fields compared by their equality operators, independently of display strings, id, or fname:

  • Rate and subclasses inheriting its equality compare the reactant and product lists and weak_type. Rates using different equality implementations compare unequal, so comparisons between base-rate wrappers and specialized rates are symmetric.

  • ReacLibRate also compares the chapter and the collection of SingleSet objects, ignoring set order but preserving duplicate counts. Each SingleSet compares its ordered coefficients, label, and flags.

  • TemperatureTabularRate and TabularWeakRate compare reactant and product lists within their respective rate families. StarLibRate additionally compares weak_type within the StarLib family.

Fields not used in equality, such as tabulated rate values, must not be added to the hash alone. These comparisons define object identity, not numerical equivalence at every temperature and density.

Rates and SingleSet objects remain mutable. Do not change their equality fields (including nested set coefficients) while using them as dictionary keys or set members. Copy a library rate before modifying it; copy its sets and coefficient arrays too if those will be changed.

Descriptive attributes#

There are several different attributes that refer to the name / properties of the rate in some way. Consider the rate for \({}^{12}\mathrm{C}(\alpha,\gamma){}^{16}\mathrm{O}\):

rl = pyna.ReacLibLibrary()
c12ag = rl.get_rate_by_name("c12(a,g)o16")

The following rate attributes are defined:

  • Rate.rid : this is a string that gives the reactants and products, using only ASCII characters. No information about the source of the rate is included.

    It is not used for library operations directly, but instead is used to build id (described next) and included as a human-readable comment in the generated rate functions in exported networks.

    For c12ag.rid, we have:

    'C12 + He4 --> O16'
    

    Note

    Other sources of \({}^{12}\mathrm{C}(\alpha,\gamma){}^{16}\mathrm{O}\) will have the same rid. For instance:

    from pynucastro.rates.alternate_rates import DeBoerC12agO16
    c12ag_deboer = DeBoerC12agO16()
    

    We would find c12ag_deboer.rid to be:

    'C12 + He4 --> O16'
    
  • Rate.id : this is intended to be a unique identifier for a rate. It is composed of the rid, any label, and the rate source (Rate.src).

    Here are several ways Rate.id is used:

    • For a Library, the main storage for rates (Library._rates) is a dictionary keyed by Rate.id.

      As a result, Rate.id must be unique in a Library and a generated network.

    • In the allowed-duplicate checks (is_allowed_dupe), together with the rate class name.

    For c12ag.id, we have:

    'C12 + He4 --> O16 <reaclib_nac2>'
    

    This is distinct from other sources of the \({}^{12}\mathrm{C}(\alpha,\gamma){}^{16}\mathrm{O}\) rate, so using c12ag_deboer defined above, we could see c12ag_deboer.id as:

    'C12 + He4 --> O16 <deboer_deboer2017>'
    
  • Rate.fname : this is a programming-language safe name for the string (no special characters except for _), and is used for the function names and rate indices in exported networks.

    This must be unique in a generated network.

    For c12ag, we have:

    'C12_He4_to_O16_reaclib'
    

    For weak rates, the weak rate type is added to the string. This is important, for example, since ReacLib provides two rates for \(p + p\), a \(\beta^+\) and \(e^-\)-capture:

    pp, pep = rl.get_rate_by_name("p(p,)d")
    

    If we look at these separately, we see:

    • pp.fname is 'p_p_to_d_beta_pos_reaclib'

    • pep.fname is 'p_p_to_d_electron_capture_reaclib'

Function arguments#

For a PythonNetwork or one of the C++ networks, a separate function is output that computes each rate. The arguments for these functions (both for the function definition and calling) are generated by py_rate_func_args and cxx_rate_func_args based on the following attributes of a Rate object:

  • rate_eval_needs_tfactors : adds Tfactors (or its C++ equivalent) to the argument list

  • rate_eval_needs_temp : adds temperature, \(T\), to the argument list

  • rate_eval_needs_logtemp : adds log base-10 temperature, \(\log_{10}(T)\), to the argument list

  • rate_eval_needs_rho : adds density, \(\rho\), to the argument list

  • rate_eval_needs_rhoye : adds the product \(\rho Y_e\), where \(Y_e\) is the electron fraction, to the argument list

  • rate_eval_needs_logrhoye : adds \(\log_{10}(\rho Y_e)\) to the argument list

  • rate_eval_needs_comp : adds the molar fractions, \(Y\), to the argument list

  • rate_eval_needs_pfcache : (C++-only) adds the partition function cache (of type part_fun::pf_cache_t) to the argument list

Copying#

A Rate is not immutable. This can be an issue when we do:

rl = pyna.ReacLibLibrary()
c12ag = rl.get_rate_by_name("c12(a,g)o16")

Here, the rate c12ag is actually a reference to the version stored internally in the Library that ReacLibLibrary creates.

This means if we modify the rate, e.g, as:

c12ag.removed = True

then our library rl is also updated. If we reuse this library, this can have unintended consequences.

As a result, when working with rates that you think may be modified, it is best to work with a copy. The recommended copy is to use the python copy module’s shallow copy:

c12ag_copy = copy.copy(c12ag)

This will invoke a custom __copy__ method in the rate that does a shallow copy for most rate attributes, but explicitly recreates the reactants, products and stoichiometry data.

Tip

When we create a RateCollection or other network, we explicitly copy the rates into the network.

Warning

For ReacLibRate, the sets that make up the rate are shared with the copy.