TO DO:

Need to be able to scatter plot measured values of Psi on top of the current Psi plot.

Alpha and rho LaTeX not working in plots.

Legend needs to be move in the Psi plot.

Consider also applying the scatter of the data and curve fit style of plotting for the parameters

Plots in general need to look better

LaTeX in all of the equations


In [38]:
import numpy as np
from scipy.integrate import quad, dblquad
%matplotlib inline
import matplotlib.pyplot as plt
import scipy.optimize as opt

This notebook calculates and plots the theoretical tilt angles. It will also plot the alpha and p0 factors vs temperature that are given in the cell below this.

Material Characteristics


In [39]:
thetamin = 25.6*np.pi/180
thetamax = 33.7*np.pi/180
t = 1*10**-6 #Cell Thickness

Data


In [40]:
tempsC = np.array([26, 27, 29, 31, 33, 35, 37])
voltages = np.array([2,3,6,7,9,11,12.5,14,16,18,20,22,23.5,26,27.5,29,31,32.5,34,36])
alpha_micro = np.array([.2575,.2475,.2275,.209,.189,.176,.15])
p0Debye = np.array([650,475,300,225,160,125,100])  #Temperature Increases to the right

In [41]:
#This Block just converts units

fields = np.array([entry/t for entry in voltages])

debye = 3.33564e-30
p0_array = np.array([entry*debye for entry in p0Debye]) #debye units to SI units

k = 1.3806488e-23
p0k_array = np.array([entry/k for entry in p0_array]) #p0k is used because it helps with the integration

KC = 273.15
tempsK = np.array([entry+KC for entry in tempsC]) #Celsius to Kelvin

alpha_array = np.array([entry*1e-6 for entry in alpha_micro])

In [88]:
PSIdata = np.array([11.4056,20.4615,25.4056,27.9021,29.028,29.6154,30.2517,30.8392,31.1329,31.5245,31.8671,32.014,32.3077,32.5034,32.7972,32.9929,33.1399,33.3357,33.4336,33.6783])
Edata = fields
T = tempsK[0]

Langevin-Debye Model

$$ U(\theta,\phi) = -\rho_0E\:sin\:\theta\:cos\:\theta\:(1+\alpha E\:cos\:\phi) $$

First, Calculate the Boltzmann Factor and the Partition Function

$$ {Boltz() returns:}\:\: e^{\frac{-U}{k_bT}}\:sin\:{\theta}\ $$

In [43]:
def Boltz(theta,phi,T,p0k,alpha,E):
    """Compute the integrand for the Boltzmann factor.
    Returns
    -------
    A function of theta,phi,T,p0k,alpha,E to be used within dblquad
    """
    return np.exp((1/T)*p0k*E*np.sin(theta)*np.cos(phi)*(1+alpha*E*np.cos(phi)))*np.sin(theta)

Second, Calculate the Tilt Angle $\psi$

$$ numerator() \:returns: {sin\:{2\theta}\:cos\:{\phi}}\:e^{\frac{-U}{k_bT}}\:sin\:{\theta} $$

In [45]:
def numerator(theta,phi,T,p0k,alpha,E):
    boltz = Boltz(theta,phi,T,p0k,alpha,E)
    return np.sin(2*theta)*np.cos(phi)*boltz
$$ denominator()\: returns: {({cos}^2{\theta} - {sin}^2{\theta}\:{cos}^2{\phi}})\:e^{\frac{-U}{k_bT}}\:sin\:{\theta} $$

In [46]:
def denominator(theta,phi,T,p0k,alpha,E):
    boltz = Boltz(theta,phi,T,p0k,alpha,E)
    return ((np.cos(theta)**2) - ((np.sin(theta)**2) * (np.cos(phi)**2)))*boltz
$$ tan(2\psi) = \frac{\int_{\theta_{min}}^{\theta_{max}} \int_0^{2\pi} {sin\:{2\theta}\:cos\:{\phi}}\:e^{\frac{-U}{k_bT}}\:sin\:{\theta}\: d\theta d\phi}{\int_{\theta_{min}}^{\theta_{max}} \int_0^{2\pi} ({{cos}^2{\theta} - {sin}^2{\theta}\:{cos}^2{\phi}})\:e^{\frac{-U}{k_bT}}\:sin\:{\theta}\: d\theta d\phi} $$

In [83]:
def compute_psi(E,p0k,alpha):
    
    def Boltz(theta,phi,T,p0k,alpha,E):
        """Compute the integrand for the Boltzmann factor.
        Returns
        -------
        A function of theta,phi,T,p0k,alpha,E to be used within dblquad
        """
        return np.exp((1/T)*p0k*E*np.sin(theta)*np.cos(phi)*(1+alpha*E*np.cos(phi)))*np.sin(theta)
    
    
    def numerator(theta,phi,T,p0k,alpha,E):
        boltz = Boltz(theta,phi,T,p0k,alpha,E)
        return np.sin(2*theta)*np.cos(phi)*boltz

    def denominator(theta,phi,T,p0k,alpha,E):
        boltz = Boltz(theta,phi,T,p0k,alpha,E)
        return ((np.cos(theta)**2) - ((np.sin(theta)**2) * (np.cos(phi)**2)))*boltz
    """Computes the tilt angle(psi) by use of our tan(2psi) equation
    Returns
    -------
    Float:
    The statistical tilt angle with conditions T,p0k,alpha,E
    """
    
    avg_numerator, avg_numerator_error = dblquad(numerator, 0, 2*np.pi, lambda theta: thetamin, lambda theta: thetamax,args=(T,p0k,alpha,E))
    
    avg_denominator, avg_denominator_error = dblquad(denominator, 0, 2*np.pi, lambda theta: thetamin, lambda theta: thetamax,args=(T,p0k,alpha,E))
    
    psi = np.arctan(avg_numerator / (avg_denominator)) * (180 /(2*np.pi)) #Converting to degrees from radians and divide by two
    
    return psi

In [84]:
compute_psi(tdata[0],p0k_array[0]*1e7,alpha_array[0]*1e10)


Out[84]:
10.344185433336435

In [91]:
PSIdata[0]


Out[91]:
11.4056

In [85]:
guess = [p0k_array[0]*1e7,alpha_array[0]*1e10]

In [86]:
guess


Out[86]:
[1570.3964686747274, 2574.9999999999995]

In [90]:
theta_best, theta_cov = opt.curve_fit(compute_psi, Edata, PSIdata,guess,absolute_sigma=True)


---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-90-fe0b4efe348c> in <module>()
----> 1 theta_best, theta_cov = opt.curve_fit(compute_psi, Edata, PSIdata,guess,absolute_sigma=True)

/usr/local/lib/python3.4/dist-packages/scipy/optimize/minpack.py in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, **kw)
    579     # Remove full_output from kw, otherwise we're passing it in twice.
    580     return_full = kw.pop('full_output', False)
--> 581     res = leastsq(func, p0, args=args, full_output=1, **kw)
    582     (popt, pcov, infodict, errmsg, ier) = res
    583 

/usr/local/lib/python3.4/dist-packages/scipy/optimize/minpack.py in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    369     if not isinstance(args, tuple):
    370         args = (args,)
--> 371     shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
    372     m = shape[0]
    373     if n > m:

/usr/local/lib/python3.4/dist-packages/scipy/optimize/minpack.py in _check_func(checker, argname, thefunc, x0, args, numinputs, output_shape)
     18 def _check_func(checker, argname, thefunc, x0, args, numinputs,
     19                 output_shape=None):
---> 20     res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
     21     if (output_shape is not None) and (shape(res) != output_shape):
     22         if (output_shape[0] != 1):

/usr/local/lib/python3.4/dist-packages/scipy/optimize/minpack.py in _general_function(params, xdata, ydata, function)
    445 
    446 def _general_function(params, xdata, ydata, function):
--> 447     return function(xdata, *params) - ydata
    448 
    449 

<ipython-input-83-73a978516109> in compute_psi(E, p0k, alpha)
     27     """
     28 
---> 29     avg_numerator, avg_numerator_error = dblquad(numerator, 0, 2*np.pi, lambda theta: thetamin, lambda theta: thetamax,args=(T,p0k,alpha,E))
     30 
     31     avg_denominator, avg_denominator_error = dblquad(denominator, 0, 2*np.pi, lambda theta: thetamin, lambda theta: thetamax,args=(T,p0k,alpha,E))

/usr/local/lib/python3.4/dist-packages/scipy/integrate/quadpack.py in dblquad(func, a, b, gfun, hfun, args, epsabs, epsrel)
    497     """
    498     return quad(_infunc, a, b, (func, gfun, hfun, args),
--> 499                 epsabs=epsabs, epsrel=epsrel)
    500 
    501 

/usr/local/lib/python3.4/dist-packages/scipy/integrate/quadpack.py in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
    309     if (weight is None):
    310         retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
--> 311                        points)
    312     else:
    313         retval = _quad_weight(func, a, b, args, full_output, epsabs, epsrel,

/usr/local/lib/python3.4/dist-packages/scipy/integrate/quadpack.py in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
    374     if points is None:
    375         if infbounds == 0:
--> 376             return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
    377         else:
    378             return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)

/usr/local/lib/python3.4/dist-packages/scipy/integrate/quadpack.py in _infunc(x, func, gfun, hfun, more_args)
    444     b = hfun(x)
    445     myargs = (x,) + more_args
--> 446     return quad(func,a,b,args=myargs)[0]
    447 
    448 

/usr/local/lib/python3.4/dist-packages/scipy/integrate/quadpack.py in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
    309     if (weight is None):
    310         retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
--> 311                        points)
    312     else:
    313         retval = _quad_weight(func, a, b, args, full_output, epsabs, epsrel,

/usr/local/lib/python3.4/dist-packages/scipy/integrate/quadpack.py in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
    374     if points is None:
    375         if infbounds == 0:
--> 376             return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
    377         else:
    378             return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)

error: Supplied function does not return a valid float.

In [ ]: