Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
self.__checks()
arg, = self.args
return self.__class__([_DivExpr([arg, _implicit_conversion(other)])])
def __rtruediv__(self, other):
self.__checks()
arg, = self.args
return self.__class__([_DivExpr([_implicit_conversion(other), arg])])
@classmethod
def from_callback(cls, callback, attr='__call__', **kwargs):
Wrapper = super().from_callback(callback, attr=attr, **kwargs)
return lambda *args, **kw: cls(Wrapper(*args, **kw))
class _NegExpr(Expr):
def _str(self, *args, **kwargs):
return "-%s" % args[0]._str(*args, **kwargs)
def __repr__(self):
return super(_NegExpr, self)._str(repr)
def __call__(self, variables, backend=math, **kwargs):
arg0, = self.all_args(variables, backend=backend, **kwargs)
return -arg0
def rate_coeff(self, *args, **kwargs): # <--- feature creep into base-class...
return -self.args[0].rate_coeff(*args, **kwargs),
class _BinaryExpr(Expr):
def __pow__(self, other):
return _PowExpr([self, _implicit_conversion(other)])
def __rpow__(self, other):
return _PowExpr([_implicit_conversion(other), self])
class _NegExpr(Expr):
def __call__(self, variables, backend=math, **kwargs):
arg0, = self.all_args(variables, backend=backend, **kwargs)
return -arg0
class _BinaryExpr(Expr):
_op = None
def _str(self, *args, **kwargs):
return ("({0} %s {1})" % self._op_str).format(*[arg._str(*args, **kwargs) for arg in self.args])
def __call__(self, variables, backend=math, **kwargs):
arg0, arg1 = self.all_args(variables, backend=backend, **kwargs)
return self._op(arg0, arg1)
class _AddExpr(_BinaryExpr):
_op = add
_op_str = '+'
class _SubExpr(_BinaryExpr):
def equilibrium_expr(self):
""" Turns self.param into a :class:`EqExpr` instance (if not already)
Examples
--------
>>> r = Equilibrium.from_string('2 A + B = 3 C; 7')
>>> eqex = r.equilibrium_expr()
>>> eqex.args[0] == 7
True
"""
from .util._expr import Expr
from .thermodynamics import MassActionEq
if isinstance(self.param, Expr):
return self.param
else:
try:
convertible = self.param.as_EqExpr
except AttributeError:
return MassActionEq([self.param])
else:
return convertible()
Returns
-------
Expr subclass for a shifted polynomial with the args: offset, p0, p1, ...
the class has the method "eval_poly" with same signature as __call__
Examples
--------
>>> P = _mk_Poly('x')
>>> p = P([3, 5, 7, 2])
>>> p.eval_poly({'x': 13}) == 5 + 7*(13-3) + 2*(13-3)**2
True
"""
class Poly(Expr):
""" Args: shift, p0, p1, ... """
argument_names = (shift_name, Ellipsis)
parameter_keys = (parameter_name,)
skip_poly = 0
def eval_poly(self, variables, backend=math):
all_args = self.all_args(variables, backend=backend)
x = variables[parameter_name]
offset, coeffs = all_args[self.skip_poly], all_args[self.skip_poly+1:]
return _eval_poly(x, offset, coeffs, reciprocal)
return Poly
def _all_keys(self, attr):
_keys = getattr(self, attr)
_all = set() if _keys is None else set(_keys)
if self.args is not None:
for arg in self.args:
if isinstance(arg, Expr):
_all = _all.union(arg._all_keys(attr))
return _all
def subclass_from_callback(cls, cb, cls_attrs=None):
""" Override MassAction.__call__ """
_RateExpr = super(MassAction, cls).subclass_from_callback(cb, cls_attrs=cls_attrs)
def wrapper(*args, **kwargs):
obj = _RateExpr(*args, **kwargs)
return cls(obj)
return wrapper
@classmethod
def from_callback(cls, callback, attr='__call__', **kwargs):
Wrapper = RateExpr.from_callback(callback, attr=attr, **kwargs)
return lambda *args, **kwargs: MassAction(Wrapper(*args, **kwargs))
class Arrhenius(Expr):
""" Rate expression for a Arrhenius-type of rate: c0*exp(-c1/T)
Examples
--------
>>> from math import exp
>>> from chempy import Reaction
>>> from chempy.units import allclose, default_units as u
>>> A = 1e11 / u.second
>>> Ea_over_R = 42e3/8.3145 * u.K**-1
>>> ratex = MassAction(Arrhenius([A, Ea_over_R]))
>>> rxn = Reaction({'R'}, {'P'}, ratex)
>>> dRdt = rxn.rate({'R': 3*u.M, 'temperature': 298.15*u.K})['R']
>>> allclose(dRdt, -3*1e11*exp(-42e3/8.3145/298.15)*u.M/u.s)
True
"""
from collections import OrderedDict
from functools import reduce
import math
from operator import add
from ..units import get_derived_unit, default_units, energy, concentration
from ..util._dimensionality import dimension_codes, base_registry
from ..util.pyutil import memoize, deprecated
from ..util._expr import Expr, UnaryWrapper, Symbol
_molar = getattr(default_units, 'molar', 1) # makes module importable.
class RateExpr(Expr):
""" Baseclass for rate expressions, see source code of e.g. MassAction & Radiolytic. """
@classmethod
@deprecated(use_instead=Expr.from_callback)
def subclass_from_callback(cls, cb, cls_attrs=None):
""" Override RateExpr.__call__
Parameters
----------
cb : callback
With signature (variables, all_args, backend) -> scalar
where `variables` is a dict, `all_args` a tuple and `backend` a module.
cls_attrs : dict, optional
Attributes to set in subclass, e.g. parameter_keys, nargs
Examples
class Symbol(Expr):
nargs = 1
def _str(self, *args, **kwargs):
uk, = self.unique_keys
return uk
def __repr__(self):
return super(Symbol, self)._str(repr)
def __call__(self, variables, backend=None, **kwargs):
uk, = self.unique_keys
return variables[uk]
class Function(Expr):
pass
class UnaryFunction(Function):
nargs = 1
_func_name = None
def __call__(self, variables, backend=math, **kwargs):
arg, = self.all_args(variables, backend=backend, **kwargs)
return getattr(backend, self._func_name)(arg)
def rate_coeff(self, *args, **kwargs):
return getattr(kwargs.get('backend', math), self._func_name)(self.args[0].rate_coeff(*args, **kwargs))
class BinaryFunction(Function):
def args_dimensionality(self, reaction):
order = reaction.order()
return (
{'time': -1, 'temperature': -1,
'amount': 1-order, 'length': 3*(order - 1)},
{'temperature': 1},
concentration
)
def __call__(self, variables, backend=math, **kwargs):
c0, c1, conc0 = self.all_args(variables, backend=backend, **kwargs)
T = variables['temperature']
return c0*T*backend.exp(-c1/T)*conc0**(1-kwargs['reaction'].order())
class EyringHS(Expr):
argument_names = ('dH', 'dS', 'c0')
argument_defaults = (1*_molar,)
parameter_keys = ('temperature', 'molar_gas_constant',
'Boltzmann_constant', 'Planck_constant')
def args_dimensionality(self, **kwargs):
return (
energy + {'amount': -1},
energy + {'amount': -1, 'temperature': -1},
concentration
)
def __call__(self, variables, backend=math, reaction=None, **kwargs):
dH, dS, c0 = self.all_args(variables, backend=backend, **kwargs)
T, R, kB, h = [variables[k] for k in self.parameter_keys]
return kB/h*T*backend.exp(-(dH-T*dS)/(R*T))*c0**(1-reaction.order())
class _MulExpr(_BinaryExpr):
_op = mul
_op_str = '*'
class _DivExpr(_BinaryExpr):
_op = truediv
_op_str = '/'
class _PowExpr(_BinaryExpr):
_op = pow
_op_str = '**'
class Constant(Expr):
nargs = 1
def __call__(self, variables, backend=None, **kwargs):
return self.args[0]
def rate_coeff(self, *args, **kwargs):
return self.args[0]
class Symbol(Expr):
nargs = 1
def _str(self, *args, **kwargs):
uk, = self.unique_keys
return uk