Cantera / cantera

Chemical kinetics, thermodynamics, and transport tool suite
https://cantera.org
Other
582 stars 342 forks source link

Extensible Interface Reactions require empty parameters in YAML #1620

Closed dstelter92 closed 3 weeks ago

dstelter92 commented 9 months ago

Recently, I was working on a custom interface reaction type via the new extensible reaction feature. A few things came up that I was asked to report here.

This issue follows the discussion here (https://groups.google.com/d/msgid/cantera-users/62e77ac7-f97a-4619-a72d-f8a95f98a4ccn%40googlegroups.com?utm_medium=email&utm_source=footer)

Consider the following user_ext.py. The ArrheniusCustomRate class asks for E and A in the YAML, but the required YAML entry is also required to include the dictionary: rate-constant: {}. This supplies no data and is not needed. I think this leads to the broader issue that reaction.cpp has logic specific to interface reactions that the new custom extensible rates get caught up in.

user_ext.py

# =========================================================================== #
# Conventional Arrhenius (interface)
# =========================================================================== #
class ArrheniusCustomRateData(ct.ExtensibleRateData):
  """
  Helper class for computing rates for the interface-arrhenius-custom-rate method
  """
  __slots__ = ("T",)
  use_count = [0]

  def __init__(self):
    self.use_count[0] += 1

  def update(self, interface):
    gas = interface.adjacent['gas'] # assume gas phase is adjacent to us
    self.T = gas.T
    return True

  def __del__(self):
    self.use_count[0] -= 1

@ct.extension(name="interface-arrhenius-custom-rate", data=ArrheniusCustomRateData)
class ArrheniusCustomRate(ct.ExtensibleRate):
  """
  Note: A required "rate-constant: {}" yaml entry is required
  """
  __slots__ = ("A","E",)
  use_count = [0]

  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.use_count[0] += 1

  def set_parameters(self, node, units):
    self.A = node["A"]
    self.E = node["E"]

  def get_parameters(self, node):
    node["A"] = self.A
    node["E"] = self.E

  def eval(self, data):
    return self.A * np.exp(-self.E / data.T)

# =========================================================================== #

We can apply this to the diamond.yaml example, by modifying one of the rates and adding

extensions:
- type: python
  name: user_ext

to the header.

For example, reaction 1 could be modified / redefined with this custom class as:

- equation: c6HH + H   <=> c6H* + H2  # Reaction 1
  type: arrhenius-custom-rate
  rate-constant: {}
  A: 1.3e+14
  E: 7.3  # not being careful about units for this example

Another (very) minor unexpected result is that the reaction type is defined as interface-arrhenius-custom-rate in user_ext.py but is called arrhenius-custom-rate in the YAML. The interface- is added automatically by Cantera. I'm not sure if this is a bug or not, but appears to be undocumented and could be confusing if multiple custom interface & bulk rates are defined with similar functional forms.

System information

Attachments

None

Additional context

None