-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Abstract
Currently, ExtensibleReactor accept only one delegate for eval. It would be very helpful if we can define multiple delegates for eval at the same time. For example define before_eval and after_eval at the same time.
Motivation
The ExtensibleReactor is very useful when we want to do some "customization" of the ODEs and equations. However, different needs of customization may require to be placed in different positions along the process. For example, the operation to change the rate constant of one reaction at every integration step is better placed before eval while the operation to impose a fixed T profile is better to be placed after eval. Below is an example of script.
class NewReactor(ct.ExtensibleReactor):
def __init__(self, phase, ramp=0.25, irxn=None, **kwargs):
super().__init__(phase, **kwargs)
# Customization 1 - change rate constant
self.irxn = irxn
self.multiplier = some_computations
# Customization 2 - Impose T profile
self.ramp = ramp
self.T_index = self.component_index('temperature')
# Customization 1 - change rate constant
def before_eval(self, t, LHS, RHS):
self.multiplier = some_computations
self.kinetics.set_multiplier(self.multiplier, self.irxn)
# Customization 2 - Impose T profile
def after_eval(self, t, LHS, RHS):
# Temperature Ramp
LHS[self.T_index] = 1.0
RHS[self.T_index] = self.rampHowever, such script is not possible because only one delegate for eval is allowed. Here is the error message.
File build/python/cantera/reactor.pyx:671, in
cantera.reactor.ExtensibleReactor.__init__()
File build/python/cantera/delegator.pyx:301, in
cantera.delegator.assign_delegates()
CanteraError: Only one delegate supported for 'eval'An alternative way would be using replace_eval containing both customization operations and the original eval method. However, it is also not possible because the original eval method seems not available to Python. Example script below:
class NewReactor(ct.ExtensibleReactor):
def __init__(self, phase, ramp=0.25, irxn=None, **kwargs):
super().__init__(phase, **kwargs)
# Obtain orginal eval method
self.original_eval = super().eval
# Customization 1 - change rate constant
self.irxn = irxn
self.multiplier = some_computations
# Customization 2 - Impose T profile
self.ramp = ramp
self.T_index = self.component_index('temperature')
def replace_eval(self, t, LHS, RHS):
# Customization 1 - change rate constant
self.multiplier = some_computations
self.kinetics.set_multiplier(self.multiplier, self.irxn)
# Original eval
self.original_eval(t, LHS, RHS)
# Customization 2 - Impose T profile
LHS[self.T_index] = 1.0
RHS[self.T_index] = self.rampWhich gives error:
Exception thrown by Python callback function:
AttributeError: 'super' object has no attribute 'eval'Therefore, it would be very helpful if it is possible to (i) define multiple delegates for eval, and/or (ii) call original eval method in replace_eval.
Thank you very much in advance for consideration.
Ps. please forgive me if a similar request has been discussed before. I tried to search within the issues but I don't find a similar topic.
Possible Solutions
As mentioned above, the possible solutions I think of within my limited knowledge on programming are as follows.
- Make it possible to define multiple delegates for
eval, e.g.,before_evalandafter_evalat the same time. - Make it possible to call the original
evalmethod in thereplace_evaldelegate.
References
None.