How can I define the numerical evaluation of a derivative of a function in sympy?
I have some functions I can describe with splines for the function and it's derivative using scipy.interpolate.
I want to manipulate some expressions with this function and then evaluate the expressions with the splines.
I can use lambdify to make a sympy function evaluate numerically as a spline.
But how can I define the derivative of a sympy function to evaluate numerically as a spline?
E.g.
import sympy as sp
import numpy as np
from scipy.interpolate import InterpolatedUnivariateSpline
from sympy.ultilitis.lambdify import implemented_function, lambdify
r = sp.symbols('r')
B = sp.symbols('B', cls=sp.Function)
B_spline = InterpolatedUnivariateSpline([1,2,3,4],[1,4,9,16])
B_der_spline = InterpolatedUnivariateSpline([1,2,3,4],[2,4,6,8])
B = implemented_function(B, lambda r: B_spline(r))
class A(sp.Function):
nargs = 2
@classfunction
def eval(cls, r, B):
return r**2*B(r)
A_eval = lambdify(r, A(r,B))
A_eval(3)
>>> 81.0
A_diff_eval = lambdify(r, sp.diff(A(r,B)))
A_diff_eval(3)
>>> NameError: global name 'Derivative' is not defined
解决方案
SymPy doesn't know how to take the derivative of the spline function, since it only has the numeric version of it from scipy.
Also, A here could just be a Python function, since you never don't evaluate it. That also makes more sense in that passing a function as an argument to a SymPy function is a bit odd.
All implemented_function does is symfunc._imp_ = staticmethod(implementation) (here symfunc = B and implementation = lambda r: B_spline(r)). You will also need to add fdiff so that it returns a new SymPy Function for B_der_spline. Something like
class B_spline_sym(Function):
_imp_ = staticmethod(B_spline)
def fdiff(self, argindex=1):
return B_der_spline_sym(self.args[0])
class B_der_spline_sym(Function):
_imp_ = staticmethod(B_der_spline)
def A(r, B):
return r**2*B(r)
Giving
In [87]: B = B_spline_sym
In [88]: A_eval = lambdify(r, A(r,B))
In [89]: A_eval(3)
Out[89]: 81.0
In [91]: A_diff_eval = lambdify(r, sp.diff(A(r,B)))
In [92]: A_diff_eval(3)
Out[92]: 108.0