I am trying to plot a 3rd rank polynomial that I calculated through Lagrance with a given set of x,y.(x=P_Maz , y=H_Maz).I can't really find what I am doing wrong.Even some plots I tried would show me wrong graph(Because x=0 wouldnt give y=25).
The equation is as follows:
3 2
3.395e-06 x - 0.001528 x + 1.976 x + 25
The part of my function and plot is this one:
P_Maz = np.array([120, 180, 270, 300]) # x
H_Maz = np.array([246, 351, 514, 572]) # y
def Lagrange(Lx, Ly):
x = symbols('x')
y = 0
for k in range(len(Lx)):
p = 1
for j in range(len(Lx)):
if j != k:
p = p * ((x - Lx[j]) / (Lx[k] - Lx[j]))
y += p * Ly[k]
return y
poly1=simplify(Lagrange(P_Maz,H_Maz))
plot(P_Maz,poly1(H_Maz))
grid()
show()
I get the following error:
Traceback (most recent call last):
File "C:\Users\Egw\Desktop\Analysh\Askhsh1\askhsh5.py", line 36, in <module>
plot(P_Maz,poly1(H_Maz))
TypeError: 'Add' object is not callable
Full code is as follows:
import numpy as np
from matplotlib.pyplot import plot, show, grid
import numpy.polynomial.polynomial as poly
import matplotlib.pyplot as plt
from scipy.interpolate import lagrange
from sympy import symbols, Eq,simplify
P_Maz = np.array([120, 180, 270, 300]) # x
H_Maz = np.array([246, 351, 514, 572]) # y
P_Lig = np.array([150, 215, 285, 300]) # x
H_Lig = np.array([307, 427, 563, 594]) # y
def Lagrange(Lx, Ly):
x = symbols('x')
y = 0
for k in range(len(Lx)):
p = 1
for j in range(len(Lx)):
if j != k:
p = p * ((x - Lx[j]) / (Lx[k] - Lx[j]))
y += p * Ly[k]
return y
poly1=simplify(Lagrange(P_Maz,H_Maz))
poly2=simplify(Lagrange(P_Lig,H_Lig))
print(Lagrange(P_Maz, H_Maz)) #Morfh Klasmatwn
print(poly1) #Telikh eksiswsh
print(lagrange(P_Maz,H_Maz)) #Telikh eksiswsh me built in method
print(Lagrange(P_Lig, H_Lig)) #Morfh Klasmatwn
print(poly2) #Telikh eksiswsh
print(lagrange(P_Lig,H_Lig)) #Telikh eksiswsh me built in method
plot(P_Maz,poly1(P_Maz))
grid()
show()
With simplify, you get an expression, but then you need to evaluate that expression for all the desired values.
You can do that through lambdify:
from sympy import lambdify
f = lambdify(x, simplify(Lagrange(P_Maz,H_Maz)), "numpy")
# above, just copied your simplify call with your variables and used in the lambdify
plot(P_Maz, f(P_Maz)) # use the created lambdify function, f, not the unevaluated expression
Mind the warning in the documentation (docs): "lambdify uses eval. Don’t use it on unsanitized input."
Related
Ive looked multiple times on google as well as on this website as well and I am still unable to solve my problem.
I have taken feedback from a previous question and decided to use a numerical bisection method however, when run the code keeps giving me this error. The code is pretty straightforward but I am basically trying to find out the EC10 and EC90 values for three different functions.
My code is:
# Imports
import numpy as np
from numpy import log as ln
from matplotlib import pyplot as plt
from random import randint
from mpmath import *
import sympy as sym
# Params
u = 10
c1 = randint(1,u)
n1 = randint(1,u)
k1 = randint(1,u)
c2 = randint(1,u)
n2 = randint(1,u)
k2 = randint(1,u)
print(f"c1 = {c1}")
print(f"n1 = {n1}")
print(f"k1 = {k1}")
print('{}(x^{})/({}+x^{})'.format(c1,n1,k1,n1))
print(f"c2 = {c2}")
print(f"n2 = {n2}")
print(f"k2 = {k2}")
print('{}(x^{})/({}+x^{})'.format(c2,n2,k2,n2))
mp.dps = 15
mp.pretty = False
# figure layout
plt.rcParams["figure.figsize"] = [7.50, 3.50]
plt.rcParams["figure.autolayout"] = True
# Hill Function for f(x) and g(x) and f(g(x))
def f(x):
return c1*(x**n1)/(k1+x**n1)
def g(x):
return c2*(x**n2)/(k2+x**n2)
def c(x):
return ((c1*x**(n2*n1))*(c2**n1))/((k2*(k2+(x**n2))**n1)+((c2**n1)*(x**(n2*n1))))
# EC finder
def BisectionEC10(fa,a,b):
c=1
x = float(np.linspace(a,b,1000))
ystar = 0.10*(fa(x).max()-fa(x).min())
while abs(fa(c)-ystar)<0.000000001:
c=(a+b)/2
if fa(c)-ystar<0:
a=c
elif fa(c)-ystar>0:
b=c
#print('The EC10 of the function is: ',"{0:.15f}".format(c))
#print('Output of the function when evaluated at the EC10: ',fa(c))
return c
def BisectionEC90(fa,a,b):
c=1
x = float(np.linspace(a,b,1000))
ystar= 0.10*(fa(x).max()-fa(x).min())
while abs(fa(c)-ystar)<0.000000001:
c=(a+b)/2
if fa(c)-ystar<0:
a=c
elif fa(c)-ystar>0:
b=c
#print('The EC90 of the function is: ',"{0:.15f}".format(c))
#print('Output of the function when evaluated at the EC90: ',fa(c))
return c
# EC90 and EC10 for f(x), g(x) and f(g(x))
up = 20
lo = 0
#x = np.linspace[lo,up,1000]
x = 1
#x = sym.symbols('x')
EC90_1 = BisectionEC90(f, lo, up)
EC10_1 = BisectionEC10(f, lo, up)
EC90_2 = BisectionEC90(g, lo, up)
EC10_2 = BisectionEC10(g, lo, up)
EC90_3 = BisectionEC90(c, lo, up)
EC10_3 = BisectionEC10(c, lo, up)
# Hill Coefficient for f(x) and g(x)
H_1 = ln(81)/(ln(EC90_1/EC10_1))
H_2 = ln(81)/(ln(EC90_2/EC10_2))
H_3 = ln(81)/(ln(EC90_3/EC10_3))
print(f"Hill's Coefficient for f(x) = {H_1}")
print(f"Hill's Coefficient for g(x) = {H_2}")
print(f"Hill's Coefficient for f(g(x)) = {H_3}")
# Plotting
plt.plot(x, f(x), color = 'red')
plt.plot(x, g(x), color = 'blue')
plt.plot(x, c(x), color = 'green')
plt.show()
My errors are:
Traceback (most recent call last):
File "/Users/*****/Documents/Python/NumericBisectionMethod/main.py", line 86, in <module>
EC90_1 = BisectionEC90(f, lo, up)
File "/Users/*****/Documents/Python/NumericBisectionMethod/main.py", line 65, in BisectionEC90
x = float(np.linspace(a,b,1000))
TypeError: only size-1 arrays can be converted to Python scalars
The float function cannot be applied to numpy arrays.
As it is, the array returned by np.linspace is already an array of doubles, so you don't need to convert it. If you ever do need to convert an array from one type to another, use arr.astype(float) or whatever.
I am trying to integrate an oscillatory expression with mpmath.quad. The integral only has one variable but I need to evaluate it in a 2D space. I need the resulting function from the integral along kx to be evaluated for a group of coordinated in x and y that defined a plane. That's why I evaluate integral(x,y) as a test in a single point of that 2D array.
This is the code I am using:
import numpy as np
from numpy.lib.scimath import sqrt
from mpmath import *
import matplotlib.pyplot as plt
mp.dps = 15
f = 8500
rho = 1.225
c0 = 343
Omega = 2*np.pi*f
k = Omega/c0
Z = -426
integrandReal = lambda kx, x, y: np.real(((2*sqrt(k**2 - kx**2)*Z)/(sqrt(k**2 - kx**2)*Z + Omega*rho))*((np.exp(1j*(kx*x + sqrt(k**2 - kx**2)*y)))/(sqrt(k**2 - kx**2))))
integrandImag = lambda kx, x, y: np.imag(((2*sqrt(k**2 - kx**2)*Z)/(sqrt(k**2 - kx**2)*Z + Omega*rho))*((np.exp(1j*(kx*x + sqrt(k**2 - kx**2)*y)))/(sqrt(k**2 - kx**2))))
integral = lambda x, y: quad(integrandReal, [-100*k, 100*k], maxdegree=10)[0] + 1j*quad(integrandImag, [-100*k, 100*k], maxdegree=10)[0]
G = integral(0.1,0.1)
I am getting the following errors when I try to evaluate the integral in an arbitrary point:
Traceback (most recent call last):
File "<ipython-input-87-901e6e5dc630>", line 1, in <module>
integral(1,1)
File "/d/dfg/Documents/ImpedanceModel/GreenImpedance.py", line 55, in <lambda>
integral = lambda x, y: quad(integrandReal, [-100*k, 100*k], maxdegree=10)[0] + 1j*quad(integrandImag, [-100*k, 100*k], maxdegree=10)[0]
File "/opt/tools/anaconda/2020.11/lib/python3.8/site-packages/mpmath/calculus/quadrature.py", line 742, in quad
v, err = rule.summation(f, points[0], prec, epsilon, m, verbose)
File "/opt/tools/anaconda/2020.11/lib/python3.8/site-packages/mpmath/calculus/quadrature.py", line 232, in summation
results.append(self.sum_next(f, nodes, degree, prec, results, verbose))
File "/opt/tools/anaconda/2020.11/lib/python3.8/site-packages/mpmath/calculus/quadrature.py", line 304, in sum_next
S += self.ctx.fdot((w,f(x)) for (x,w) in nodes)
File "/opt/tools/anaconda/2020.11/lib/python3.8/site-packages/mpmath/ctx_mp_python.py", line 944, in fdot
for a, b in A:
File "/opt/tools/anaconda/2020.11/lib/python3.8/site-packages/mpmath/calculus/quadrature.py", line 304, in <genexpr>
S += self.ctx.fdot((w,f(x)) for (x,w) in nodes)
TypeError: <lambda>() missing 2 required positional arguments: 'x' and 'y'
I thought the error was because I wasn't defining the arguments in the integration as it has to be done with scipy.integrate.quad (as you can see in one of my last posts) but with mpmath I don't know what is generating this error.
Thanks in advance for any help!
You need to pass x and y to your lambdas (integrandReal and integrandImag). Also, there is another issue with your example as you try to subscript the mpc object returned by quad. I removed it to get a result, it shows you how to pass x and y through the calls, but I cannot assure you the numerical result is correct:
integral = lambda x, y: quad(integrandReal, [-100*k, 100*k], [x], [y], maxdegree=10) + 1j*quad(integrandImag, [-100*k, 100*k], [x], [y], maxdegree=10)
G = integral(0.1,0.1)
# Returns: mpc(real='0.0', imag='0.0')
I have just installed scipy and tried few example codes. My scipy version is 0.17.0. But I can't figure out what's wrong going with scipy.integrate.solve_bvp. I am trying to run the following code from this link,
# In the second example we solve a simple Sturm-Liouville problem::
# y'' + k**2 * y = 0
# y(0) = y(1) = 0
# It is known that a non-trivial solution y = A * sin(k * x) is possible for
# k = pi * n, where n is an integer. To establish the normalization constant
# A = 1 we add a boundary condition::
# y'(0) = k
# Again we rewrite our equation as a first order system and implement its
# right-hand side evaluation::
# y1' = y2
# y2' = -k**2 * y1
import numpy as np
from scipy.integrate import solve_bvp
def fun(x, y, p):
k = p[0]
return np.vstack((y[1], -k**2 * y[0]))
# Note that parameters p are passed as a vector (with one element in our
# case).
# Implement the boundary conditions:
def bc(ya, yb, p):
k = p[0]
return np.array([ya[0], yb[0], ya[1] - k])
# Setup the initial mesh and guess for y. We aim to find the solution for
# k = 2 * pi, to achieve that we set values of y to approximately follow
# sin(2 * pi * x):
x = np.linspace(0, 1, 5)
y = np.zeros((2, x.size))
y[0, 1] = 1
y[0, 3] = -1
# Run the solver with 6 as an initial guess for k.
sol = solve_bvp(fun, bc, x, y, p=[6])
# We see that the found k is approximately correct:
sol.p[0]
# 6.28329460046
# And finally plot the solution to see the anticipated sinusoid:
x_plot = np.linspace(0, 1, 100)
y_plot = sol.sol(x_plot)[0]
plt.plot(x_plot, y_plot)
plt.xlabel("x")
plt.ylabel("y")
plt.show()
I am getting this error,
Traceback (most recent call last):
File "my.py", line 19, in <module>
from scipy.integrate import solve_bvp
ImportError: cannot import name solve_bvp
Why I am getting this error? Other scipy integrators like scipy.integrate.odeint, scipy.integrate.ode are working fine.
If you go to the documentation for the function, under the heading "Notes" you will see that the function is new as of version 0.18.0
I'm trying to calculate the roots for a function using the scipy function fsolve, but an error keeps flagging:
TypeError: 'numpy.array' object is not callable
I assume it's probably easier to define the equation as a function but I've tried that a few times to no avail.
Code:
import scipy
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
# Constants
wavelength = 0.6328
ncore = 1.462420
nclad = 1.457420
a = 8.335
# Mode Order
l = 0
# Mode parameters
V = (2 * np.pi * a / wavelength) * np.sqrt(ncore**2 - nclad**2)
U = np.arange(0, V, 0.01)
W = np.sqrt(V**2-U**2)
func = U * scipy.special.jv(l+1, U) / scipy.special.jv(l, U) - W * scipy.special.kv(l+1, W) / scipy.special.kv(l, W)
from scipy.optimize import fsolve
x = fsolve(func,0)
print x
StackTrace:
Traceback (most recent call last):
File "<ipython-input-52-081a9cc9c0ea>", line 1, in <module>
runfile('/home/luke/Documents/PythonPrograms/ModeSolver_StepIndex/ModeSolver_StepIndex.py', wdir='/home/luke/Documents/PythonPrograms/ModeSolver_StepIndex')
File "/usr/lib/python2.7/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 580, in runfile
execfile(filename, namespace)
File "/home/luke/Documents/PythonPrograms/ModeSolver_StepIndex/ModeSolver_StepIndex.py", line 52, in <module>
x = fsolve(func,0)
File "/usr/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 140, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "/usr/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 197, in _root_hybr
shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))
File "/usr/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 20, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
TypeError: 'numpy.ndarray' object is not callable
That is because fsolve takes a function as argument.
Try this, Note you still will encounter some runtime error , you will have to check if your return from func is properly constructed, I will leave that for you to figure out.
import scipy
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
# Constants
wavelength = 0.6328
ncore = 1.462420
nclad = 1.457420
a = 8.335
# Mode Order
# l = 0
# Mode parameters
V = (2 * np.pi * a / wavelength) * np.sqrt(ncore**2 - nclad**2)
U = np.arange(0, V, 0.01)
W = np.sqrt(V**2-U**2)
def func(l):
return U * scipy.special.jv(l+1, U) / scipy.special.jv(l, U) - W * scipy.special.kv(l+1, W) / scipy.special.kv(l, W)
from scipy.optimize import fsolve
x = fsolve(func,0)
print x
You need to pass a function to fsolve not an array.
If I just print your func:
func
array([ -1.04882076e+01, -1.04881526e+01, -1.04879876e+01,
-1.04877125e+01, -1.04873274e+01, -1.04868321e+01,
-1.04862266e+01, -1.04855109e+01, -1.04846847e+01,
-1.04837481e+01, -1.04827008e+01, -1.04815428e+01,
-1.04802738e+01, -1.04788938e+01, -1.04774024e+01,
-1.04757996e+01, -1.04740850e+01, -1.04722585e+01,
-1.04703198e+01, -1.04682686e+01, -1.04661046e+01,
-1.04638275e+01, -1.04614371e+01, -1.04589330e+01,
-1.04563147e+01, -1.04535820e+01, -1.04507345e+01,
-1.04477718e+01, -1.04446934e+01, -1.04414988e+01,
... ]
that's an array but you want a function. Something like this works:
def linear(x):
return 2*x+4
fsolve(linear, 0)
don't know how one could define your function, though.
I am trying to fit resistivity vs temperature data to Bloch-Gruneisen formula for resistivity in metals:
function
as you can see there is an integral function with a parametric limit. I don't know how to implement an algorithm to run a least squares fit.
I came up with:
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
import scipy as sp
from scipy.optimize import leastsq
#retrieve data from file
data = pl.loadtxt('salita.txt')
Temp = data[:, 0]
Res = data[:, 2]
def debye_func(p, T, r):
rho0, AD, TD = p
coeff = AD*np.power(T, 5)/np.power(TD, 4)
f = np.power(x^5)/np.power(np.sinh(x), 2) #function to integrate
err_debye = r - rho0 - coeff * #integral???
return err_debye
p0 = sp.array([0.0001 , 0.00001, 50])
plsq = leastsq(debye_func, p0, args=(Temp, Res))
print plsq
Ideas on how could I write it?
EDIT: my code has become:
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
import scipy as sp
from scipy.optimize import leastsq
from scipy.integrate import quad
#retrieve data from file
data = pl.loadtxt('salita.txt')
Temp = data[:, 0]
Res = data[:, 2]
def debye_integrand(x):
return np.power(x, 5)/np.power(np.sinh(x), 2)
def debye_func(p, T, r):
rho0, AD, TD = p
coeff = AD*np.power(T, 5)/np.power(TD, 4)
err_debye = r - rho0 - coeff * quad(debye_integrand, 0, TD/(2*T))
return err_debye
p0 = sp.array([0.0001 , 0.00001, 50])
plsq = leastsq(debye_func, p0, args=(Temp, Res))
print plsq
Now I get a ValueError:
Traceback (most recent call last):
File "debye.py", line 24, in <module>
plsq = leastsq(debye_func, p0, args=(Temp, Res))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 348, in leastsq
m = _check_func('leastsq', 'func', func, x0, args, n)[0]
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 14, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "debye.py", line 19, in debye_func
err_debye = r - rho0 - coeff * quad(debye_integrand, 0, TD/(2*T))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/quadpack.py", line 247, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/quadpack.py", line 296, in _quad
if (b != Inf and a != -Inf):
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I think that means I'm providing leastsq an argument it can't take, but I don't know how to modify my code.
EDIT2: I solved my equation analytically with Maxima and I got
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
import scipy as sp
from scipy.optimize import leastsq
from scipy.integrate import quad
from scipy.special import zetac
from mpmath import polylog
#retrieve data from file
data = pl.loadtxt('salita.txt')
Temp = data[:, 0]
Res = data[:, 2]
def debye_integrand(x):
return np.power(x, 5)/np.power(np.sinh(x), 2)
def debye_func(p, T, r, integral):
rho0, AD, TD = p
coeff = AD*np.power(T, 5)/np.power(TD, 4)
den = np.exp(TD/T) -1
m1 = 5*((TD/(2*T))**4)*np.log(np.exp(TD/(2*T)+1)*(np.exp(TD/T)-1)+120*polylog(5, np.exp(TD/(T))*(1-np.exp(TD/(2*T)))
m2 = 120*(TD/(2*T))*polylog(4, np.exp(TD/(2*T)))*(np.exp(np.exp(TD/T))-1)+60*((TD/(2*T))**2)*polylog(3, np.exp(TD/(2*T))*(1-np.exp((TD/(2*T)))
m3 = 20*((TD/(2*T))**3)*polylog(2, np.exp(TD/(2*T))*(np.exp(TD/T)-1)+120**polylog(5, -np.exp(TD/(2*T)))*(1-np.exp(TD/T))
m4 = 120*(TD/(2*T))*polylog(4, -np.exp(TD/(2*T)))*(np.exp(TD/T)-1)+60*((TD/(2*T))**2)*polylog(3, -np.exp(TD/(2*T)))*(1-np.exp(TD/T))
m5 = 20*((TD/(2*T))**3)*polylog(2, -np.exp(TD/(2*T)))*(np.exp(TD/T)-1) -2*((TD/(2*T))**5)*np.exp(TD/T)
m6 = 5*((TD/(2*T))**4)*np.log(1-np.exp(TD/(2*T))*(np.exp(TD/T)-1)
zeta = 15.0*zetac(5)/2
integral = (m1+m2+m3+m4+m5+m6)/den +zeta
err_debye = r - rho0 - coeff * integral
return err_debye
#initizalied with Einstein model fit
p0 = sp.array([0.00001 , 0.0000001, 70.0])
plsq = leastsq(debye_func, p0, args=(Temp, Res))
print plsq
It says SyntaxError: invalid syntax in m2. I tried to do it with loops in the numerical way, but I didn't succeed.
My .txt file is here, if you want to try. First column is temperature, third one is resistivity.
You could, for instance, separately define the integrand function,
def debye_integrand(x, n):
return x**n/((np.exp(x) - 1)*(1 - np.exp(-x)))
and then use scipy.integrate.quad to do this integration numerically,
from scipy.integrate import quad
def debye_func(p, T, r):
# [...] the rest of your code from above here
err_debye = r - rho0 - coeff * quad(debye_integrand, 0, T/TD, args=(n,))
return np.sum(err_debye**2)
That's the general idea, and this might need to be adapted further to your code. An ideal solution would be to find an analytical solution to that integral, or rewrite it with classical integral functions from scipy.special, but it might not be straightforward (see below).
Also you should use the more general scipy.opitimize.minimize function instead of the least-square fit, since it provides algorithms that are more efficient and robust for non-smooth optimizations. The default optimization method BFGS is a good start.
Edit: actually, there is an analytical solution to this integral (for n=5), that you can obtain, for instance, with Maxima,
>> integrate(x**5/((exp(x) - 1)*(1 - exp(-x))), x, 0, a)
where a is the integration limit, li_k the Polylogarithm function of order k (see mpmath.polylog) and ζ is the Riemann Zeta function (see scipy.special.zetac).
Although, depending on your needs, it might be faster to just go with a numerical integration (or pre-calculated table lookup) rather than puyting all of this together, and converting it to python.
Edit 2: Here the final solution with analytical calculation of the integral,
import numpy as np
import mpmath as mp
from scipy.optimize import minimize
from scipy.integrate import quad
import matplotlib.pyplot as plt
def debye_integral_sym_scalar(x):
"""
Calculate the Debye integral for a scalar using multi precision math,
as otherwise it overflows with 64bit floats
"""
exp_x = mp.exp(x)
m1 = -120*mp.polylog(5, exp_x)
m2 = 120*x*mp.polylog(4, exp_x)
m3 = -60*x**2*mp.polylog(3, exp_x)
m4 = 20*x**3*mp.polylog(2, exp_x)
m5 = 5*x**4*mp.log(1 - exp_x)
m6 = - x**5*exp_x
return m1 + m2 + m3 + m4 + m5 + m6/(exp_x - 1) + 120*mp.zeta(5)
# this is the actual function that we can use
def debye_integral_sym(x):
f = np.vectorize(debye_integral_sym_scalar, otypes=[np.complex])
return f(x).real
def debye_integrand(x, n):
return x**n/((np.exp(x) - 1)*(1 - np.exp(-x)))
# test that debye_integral_sym returns the same result as quad
a = 10.0
res0 = quad(debye_integrand, 0, a, args=(5,))[0]
res1 = debye_integral_sym(a)
np.testing.assert_allclose(res0, res1)
def resistivity_fit(p, T):
rho0, AD, TD = p
coeff = AD*np.power(T, 5)/np.power(TD, 4)
return rho0 + coeff * debye_integral_sym(TD/(2*T))
def debye_err_func(p, T, r):
return np.sum((r - resistivity_fit(p, T))**2)
# wget "http://pastebin.com/raw.php?i=tvzcdxYA" -O salita.txt
data = np.loadtxt('salita.txt')
temp_exp = data[:, 0]
res_exp = data[:, 2]
p0 = np.array([0.0001 , 0.00001, 50])
p_opt = minimize(debye_err_func, p0, args=(temp_exp, res_exp))
print p_opt
temp = np.linspace(temp_exp.min(), temp_exp.max(), 100)
plt.plot(temp_exp, res_exp, '.', label='Experimental data')
plt.plot(temp, resistivity_fit(p_opt.x, temp), 'r', label='Bloch-Gruneisen fit')
plt.legend(loc='best')
plt.xlabel('Temperature [K]')
plt.ylabel('Resistivity')
plt.show()
With the output of the optimization function,
status: 0
success: True
njev: 5
nfev: 25
hess_inv: array([[ 7.32764243e-01, -4.89555962e-01, -1.93879729e-08],
[ -4.89555962e-01, 3.27690582e-01, -2.09510086e-08],
[ -1.93879729e-08, -2.09510086e-08, 1.00000000e+00]])
fun: 1.784420370873494e-11
x: array([ 9.96468440e-06, 7.40349389e-06, 5.00000000e+01])
message: 'Optimization terminated successfully.'
jac: array([ -1.11880569e-06, 1.28115957e-06, 2.31303410e-12])
and the resulting plot,