To preface this question, I understand that it could be done better. But this is a question in a class of mine and I must approach it this way. We cannot use any built in functions or packages.
I need to write a function to approximate the numerical value of the second derivative of a given function using finite difference. The function is below we are using.
2nd Derivative Formula (I lost the login info to my old account so pardon my lack of points and not being able to include images).
My question is this:
I don't understand how to make the python function accept the input function it is to be deriving. If someone puts in the input 2nd_deriv(2x**2 + 4, 6) I dont understand how to evaluate 2x^2 at 6.
If this is unclear, let me know and I can try again to describe. Python is new to me so I am just getting my feet wet.
Thanks
you can pass the function as any other "variable":
def f(x):
return 2*x*x + 4
def d2(fn, x0, h):
return (fn(x0+h) - 2*fn(x0) + fn(x0-h))/(h*h)
print(d2(f, 6, 0.1))
you can't pass a literal expression, you need a function (or a lambda).
def d2(f, x0, h = 1e-9):
func = f
if isinstance(f, str):
# quite insecure, use only with controlled input
func = eval ("lambda x:%s" % (f,))
return (func(x0+h) - 2*func(x0) + func(x0-h))/(2*h)
Then to use it
def g(x):
return 2*x**2 + 4
# using explicit function, forcing h value
print d2(g, 6, 1e-10)
Or directly:
# using lambda and default value for h
print d2(lambda x:2x**2+4, 6)
EDIT
updated to take into account that f can be a string or a function
Related
I am using sympy to help automate the process of finding equations of motion for some systems using the Euler Lagrange method. What would really make this easy is if I could define a function q and specify its time derivative qd --> d/dt(q) = qd. Likewise I'd like to specify d/dt(qd) = qdd. This is helpful because as part of the process of finding the equations of motion, I need to take derivatives (with respect to time, q, and qd) of expressions that are functions of q and qd. In the end I'll end up with an equation in terms of q, qd, and qdd and I'd like to be able to either print this neatly or use lambdify to convert this to a neat numpy function for use in a simulation.
Currently I've accomplished this is a very roundabout and annoying way by defining q as a function and qd as the derivative of that function:
q = sympy.Function('q', real=True)(t)
q_diff = diff(q,t)
This is fine for most of the process but then I end up with a messy expression filled with "Derivative (q, t)" and "Derivative (Derivative(q, t), t)" which is hard to wrangle into a neat printing format and difficult to turn into a numpy function using lambdify. My current solution is thus to use the subs function and replace q_diff and diff(q_diff, t) with sympy symbols qd and qdd respectively, which cleans things up and makes manipulating the expression much easier. This seems like a bad hack though and takes tons of time to do for more complicated equations with lots of state variables.
What I'd like is to define a function, q, with a specific value for the time derivative. I'd pass in that value when creating the function, and sympy could treat it like a generic Function object but would use whatever I'd given it for the time derivative instead of just saying "Derivative(q, t)". I'd like something like this:
qdd = sympy.symbols('qdd')
qd = my_func(name='qd', time_deriv=qdd)
q = my_func(name='q', time_deriv=qd)
diff(q, t)
>>> qd
diff(q**2, t)
>>> 2*q*qd
diff(diff(q**2, t))
>>> 2*q*qdd + 2*qd**2
expr = q*qd**2
expr.subs(q, 5)
>>> 5*qd**2
Something like that, where I could still use the subs command and lambdify command to substitute numeric values for q and qd, would be extremely helpful. I've been trying to do this but I don't understand enough of how the base sympy.Function class works to get this going. This is what I have right now:
class func(sp.Function):
def __init__(self, name, deriv):
self.deriv = deriv
self.name = name
def diff(self, *args, **kwargs):
return self.deriv
def fdiff(self, argindex=1):
assert argindex == 1
return self.deriv
This code so far does not really work, I don't know how to specify that specifically the time derivative of q is qd. Right now all derivatives of q are returning q?
I don't know if this is just a really bad solution, if I should be avoiding this issue entirely, or if there's already a clean way to solve this. Any advice would be very appreciated.
I am trying to approximate the Gauss Linking integral for two straight lines in R^3 using dblquad. I've created this pair of lines as an object.
I have a form for the integrand in parametrisation variables s and t generated by a function gaussint(self,s,t) and this is working. I'm then just trying to define a function which returns the double integral over the two intervals [0,1].
Edit - the code for the function looks like this:
def gaussint(self,s,t):
formnum = self.newlens()[0]*self.newlens()[1]*np.sin(test.angle())*np.cos(test.angle())
formdenone = (np.cos(test.angle())**2)*(t*(self.newlens()[0]) - s*(self.newlens()[1]) + self.adists()[0] - self.adists()[1])**2
formdentwo = (np.sin(test.angle())**2)*(t*(self.newlens()[0]) + s*(self.newlens()[1]) + self.adists()[0] + self.adists()[1])**2
fullden = (4 + formdenone + formdentwo)**(3/2)
fullform = formnum/fullden
return fullform
The various other function calls here are just bits of linear algebra - lengths of lines, angle between them and so forth. s and t have been defined as symbols upstream, if they need to be.
The code for the integration then just looks like this (I've separated it out just to try and work out what was going on:
def approxint(self, s, t):
from scipy.integrate import dblquad
return dblquad(self.gaussint(s,t),0,1, lambda t:0,lambda t:1)
Running it gets me a lengthy bit of somewhat impenetrable process messages, followed by
ValueError: invalid callable given
Any idea where I'm going wrong?
Cheers.
If I use functions in SymPy and call the diff method, the commutative property just gets ignored.
h = Function('h',real=True,commutative=False)(t)
R = Function('R',real=True,commutative=False)(t)
print(diff(R*h,t))
# returns:
R(t)*Derivative(h(t), t) + h(t)*Derivative(R(t), t)
Am I doing something wrong here? I just want the output to have R in the front always..
This is arguably a bug in SymPy, which determines the commutativity of a function from its arguments. See also this comment. It's not related to derivatives: simply printing h*R will expose the bug (the expression is presented as R(t)*h(t)).
Until this behavior is changed, it seems the only way to achieve the desired result is to declare t to be noncommutative:
t = Symbol('t', commutative=False)
h = Function('h', real=True)(t)
R = Function('R', real=True)(t)
print(diff(R*h, t))
prints
R(t)*Derivative(h(t), t) + Derivative(R(t), t)*h(t)
My question is if there's a way to take some values in a function that are not
integrated in odeint.
Exemple: if I have a derivative dy(x)/dt = A*x+ln(x) and before to get this equation I computed A throught of a intermediate equation like A = B*D . I would like to take the A's value during the process.
More detailed (only exemple):
def func(y,t)
K = y[0]
B = 3
A = cos(t**2) + B
dy/dt = A*t+ln(t)
return [dy/dt]
Can I take A's values of function?
The answer for Josh Karpel
The code is like that:
def Reaction(state,t):
# Integrate Results
p = state[0]
T = state[1]
# function determine enthalpy of system
f1(T,p) = enthalpy
# function determine specific volume of system
f2(T,p) = specific volume
# function determine heat release by reactions
f3(T,p,t) = heat release by reactions
# Derivatives
dp/dt = f(T,p,enthalpy,specific volume,heat release by reactions)
dT/dt = f(T,p,enthalpy,specific volume,heat release by reactions)
The real code is bigger than that. But, I would like to know if there is a way to store the values of f1 (enthalpy), f2 (specific volume), f3 (heat release) as a vector or tuple during the process of solution of odeint with the same size of p and T.
It's not entirely clear what you want, but it sounds like you need to pass another value to the function you're integrating over. There are two options I can think of:
scipy.integrate.odeint takes an args argument which contains extra arguments to be passed to the integrand function, which could then have signature y(t, A).
You could use functools.partial to construct a new function which has the argument A for the integrand function y(t, A) already set.
I want to use the newton function loaded as
from scipy.optimize import newton
in order to find the zeros of a function enetered by the user. I write a script that first ask to the user to specify a function together with its first derivative, and also the starting point of the algorithm. First of all typing help(newton) I saw which parameters takes the function and the relative explanation:
newton(func, x0, fprime=None, args=(), tol=1.48e-08, maxiter=50)
func : function
The function whose zero is wanted. It must be a function of a
single variable of the form f(x,a,b,c...), where a,b,c... are extra
arguments that can be passed in the `args` parameter.
In which way I have to pass my function? If I use for func e.g. x**3 (and its first derivative) the response is NameError: name 'x' is not defined. On the internet I find that first I have to define my function and its first derivative and pass the names as parameters. So I made the following
fie = raw_input('Enter function in terms of x (e.g. x**2 - 2*x). F= ')
dfie = raw_input('Enter first derivative of function above DF = ')
x0 = input('Enter starting point x0 = ')
def F(x,fie):
y = eval(fie)
return y
def DF(x, dfie):
dy = eval(dfie)
return dy
print newton(F,x0,DF)
But I get the output
102 for iter in range(maxiter):
103 myargs = (p0,) + args
--> 104 fder = fprime(*myargs)
105 if fder == 0:
106 msg = "derivative was zero."
TypeError: DF() takes exactly 2 arguments (1 given)
and the same issue for F if I omit DF. Looking at the code in /usr/local/share/src/scipy/scipy/optimize/zeros.py I see that it evaluates the first derivative with fder=fprime(*myargs) so maybe I have to put in args something that make it working. I was thinking about it but no solution comes to me.
First, be aware that using eval makes your program vulnerable to malicious users. If that concern does not apply, you can create F and DF like this:
F = eval('lambda x :'+fie)
DF = eval('lambda x :'+dfie)
Then both functions expect only a single argument, and you can leave the args argument empty.
EDIT. If you really want to stick to your code as closely as possible, this should also work, but it does not look very nice to me. newton will send the same args to both functions.
def F(x,fie,dfie):
y = eval(fie)
return y
def DF(x,fie,dfie):
dy = eval(dfie)
return dy
print newton(F,x0,DF,(fie,dfie))