Question about mathematical integration for a differential equation - python

I'm new to coding, so have patience please. I have an exercise where the aim is to solve a differential equation, where there is a function that has an integral of the form dx cos(x)**2 between 0 and t.
I've tried defining a function, then using the definition to attempt to get a final value at the end of the programme.
import numpy
from scipy import integrate
def dydt(C,y,t):
return -C*y
def f_2(x):
return numpy.sin(x)**2
def C(t):
return 1+ integrate.quad(f_2,0,t)
t=numpy.linspace(0,10,100)
y=integrate.odeint(dydt,[1.0],t)
This is the error I'm getting: TypeError: dydt() missing 1 required positional argument: 't' --> I know I have clearly defined my t, so what am I doing wrong? Cheers!

dydt(C,y,t) should be dydt(C,y)
import numpy
from scipy import integrate
def dydt(C,y):
return -C*y
def f_2(x):
return numpy.sin(x)**2
def C(t):
return 1+ integrate.quad(f_2,0,t)
t=numpy.linspace(0,10,100)
y=integrate.odeint(dydt,[1.0],t) # works fine
print(y)

Related

Pass function that takes kwargs to solve_ivp

For a class, I am using solve_ivp to solve a differential equation function that I customize using keyword arguments. Here is my differential equation function integrate and the function sineCurrent I pass to it to help generate the differential equation. I already know that calling sineCurrent within integrate works. My issue arises when I try to pass integrate and by extension sineCurrent to solve_ivp. My class requires that they all remain separate functions.
def integrate(time,**kwargs):
func = kwargs['current']
V = kwargs['voltage']
Cm = 0.2 # membrane capacitance in nF
R = 100 # membrane resistance in mega-ohms
V_rest = -60 # resting membrane voltage in mV
I = func(time,**kwargs) # passing arguments current input function
s = I*R
dVdt = (V_rest-V+s)/(Cm*R)
return dVdt
def sineCurrent(time,**kwargs):
# Passing frequency and current arguments, setting defaults to f=0.5 kHz and I=2 nA
defaultKwargs = { 'freq': float("0.5"), 'Imax': float("2"),}
kwargs = { **defaultKwargs, **kwargs }
freq = kwargs['freq']
Imax = kwargs['Imax']
# Error message if time vector not included
if len(time) == 0:
return "sineCurrent requires at least one input parameter, time"
# Calculating sineCurrent
I = Imax*np.sin(2*pi*freq*time)
return I
I tried several methods to pass integrate to solve_ivp. First, I tried using the basicsolve_ivp syntax.
t = np.arange(-10,100,0.1)
V_init= np.array([50])
soln = solve_ivp(integrate,t,current=sineCurrent,[t[0], t[-1]],V_init)
This yielded the error SyntaxError: positional argument follows keyword argument. Next I tried using a lambda function.
t = np.arange(-10,100,0.1)
V_init= np.array([50])
soln = solve_ivp(integrate=lambda t,current=sineCurrent: [t[0], t[-1]],V_init)
This led to the same error message as before. So I moved the keyword arguments to the end.
t = np.arange(-10,100,0.1)
V_init= np.array([50])
soln = solve_ivp(integrate,[t[0], t[-1]],V_init,args=(t,current=sineCurrent,voltage=V_init))
This led to the error message SyntaxError: invalid syntax. I am at a loss as to what to try next. I know that my integrate function can produce an np.ndarray when arguments are passed to it properly, shown below, but I cannot figure out how to pass integrate to solve_ivp.
dVdt = integrate(t,current=sineCurrent,voltage=V_init)

solve equation in python with sympy

I want to solve an equation in python but I keep getting this error:
__new__() missing 1 required positional argument: 'name'
and my code is as below:
import sympy as sym
sym.init_printing()
x,y,z = sym.symbols('x,y,z')
c1 = sym.Symbol('c1')
f=sym.Eq(2*x**2+y+z,1)
g=sym.Eq(x+2*y+z,c1)
h=sym.Eq(-2*x+y,-z)
sym.solve([f,g,h],(x,y,z))

conversion of function from Matlab to python

I have a MATLAB function :
Bits=30
NBits= ceil(fzero(#(x)2^(x) - x -1 - Bits, max(log2(Bits),1)))
I want to convert it to python, I wrote something like this so far:
from numpy import log, log2
from scipy.optimize import root_scalar
def func(x,Bits):
return ((x)2^(x)-x-1-Bits, max(log2(Bits)))
However it says that it need to be (x)*2^
Does anybody know first, if the conversion from Matlab to python is correct? and second if * has to be added?
Upon suggestion I wrote this lambda function:
lambda x: (2^(x) -x -1 -Bits) , max(log2(Bits))
but I get this error:
TypeError: 'numpy.float64' object is not iterable
I don't have numpy or scipy on this computer so here is my best attempt at an answer.
def YourFunc(Bits):
return math.ceil(root_scalar(lambda x: (2**x)-x-1-Bits, x0 = max(log2(Bits),1)))
Bits = 30
NBits = YourFunc(30)
print(NBits)
I used this function for log2 rather than the one from numpy. Try it
def log2(x):
return math.log(x,2)

python integration issue, the function with exponential

I would like to integrate the function e^(-x**2/2) by simpson rule
but it is keep having an error and I don't know what is the problem.
a=eval(input('a:'))
b=eval(input('b:'))
n=eval(input('n:'))
def f(x):
e**(-x**2/2)
h=(b-a)/n
s= f(a)+f(b)
def simpson_rule(f(x),a,b,n):
#Approximation by Simpson's rule
c=(a+b)/2.0
h=abs(b-a)/2.0
return h*(f(a)+4.0*f(c)+f(b))/3.0
def simpson_rule(f(x),a,b,n):
"""Approximates the definite integral of f from a to b by the composite Simpson's rule, using n subintervals"""
for i in range (1,n,2):
s+=4*f(a+i*h)
for i in range(2,n-1,2):
s+=2*f(a+i*h)
return s*h/3
print simpson_rule(f(x),a,b,n)
You define 2 integration routines with the same name. Which one do you expect to run if you call simpson_rule()?
The first one is the special case where n=1. You might rename it accordingly.
Second, your call is print simpson_rule(f(x),a,b,n) but you only need to hand over f() to the function, like this print simpson_rule(f,a,b,n).
You can see that f is a function, and f() is a function return value:
def f(x):
return x + 13
f
<function f at 0x0000000002253D68>
f(5)
18
Try it out and if you still have errors please post the error message(s).

quadpack.error: Supplied function does not return a valid float in python

I would like to integrate a function with respect to (z) and make (x) and (y) as arguments. My goal is to get the result of integration at different location (x,y), In this case, I should get 16 values of integration which correspond to (x1,y1), (x1,y2) ..., (x2,y1) ... and so on.
This is the code:
import numpy as np
import math
import scipy.integrate
a = 5
b = 6
xn=np.linspace(0,3,4)
yn=np.linspace(3,6,4)
x,y=np.ix_(xn,yn)
def fun(z,x,y):
model=(x**2/a**2+y**2/b**2+z**2/a**2)**0.5
#print(model)
return model
def int(x,y):
int=scipy.integrate.quad(fun,0,10,args=(x,y,))[0]
print (int)
return int
integral = int(x,y)
print (integral)
But I got this error message:
....
int=scipy.integrate.quad(model,0,10,args=(x,y,))[0]
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-
packages/scipy/integrate/quadpack.py", line 254, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-
packages/scipy/integrate/quadpack.py", line 319, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
quadpack.error: Supplied function does not return a valid float.
Please could anyone show me how to fix this error and thank you in advance.
As the error suggests, your fun function should be returning a float but is instead returning a 2D array:
[[ 1.11803399 1.20185043 1.30170828 1.41421356]
[ 1.13578167 1.21837779 1.31698308 1.42828569]
[ 1.18743421 1.26666667 1.36177988 1.46969385]
[ 1.26885775 1.34329611 1.43333333 1.53622915]]
The function that you are integrating should evaluate to a single number at some point in parameter space.
If you are trying to do an N dimensional integral, you may want to look at scipy.integrate.nquad.

Categories