In [1]:
%pylab inline

from sympy.utilities.lambdify import lambdify
from sympy import init_session
init_session()

from numpy import arange, abs

from pandas import DataFrame

from pylab import plot
import matplotlib.pyplot as plt


Populating the interactive namespace from numpy and matplotlib
IPython console for SymPy 0.7.3 (Python 3.3.2-64-bit) (ground types: python)

These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)

Documentation can be found at http://www.sympy.org

In [2]:
function = x*tanh(sin(x)+pi/3)
dfunction = function.diff(x)
d2function = dfunction.diff(x)
numFunction = lambdify(x, function, "numpy")
dnumFunction = lambdify(x, dfunction, "numpy")
d2numFunction = lambdify(x, d2function, "numpy")
d4f = lambdify(x, d2function.diff(x, 2), "numpy")

order = 200

t = pylab.linspace(-10, 10, 1000)
fig, axes = plt.subplots(figsize=(15,8))
axes.plot(t, numFunction(t))


Out[2]:
[<matplotlib.lines.Line2D at 0x7f631746c190>]

In [3]:
def maximum(f, start, end):
    from scipy.optimize import minimize_scalar
    return f(minimize_scalar(lambda x: -f(x), bounds=(start, end), method='bounded').x)

In [7]:
def calcM(points, values, lengths, diffOnEdges=False):
    order = len(points)
    W = ma.zeros((order-2, order-2))
    for k in range(order-3):
        W[k][k+1] = lengths[k+1]/6
        W[k+1][k] = lengths[k+1]/6
        W[k][k] = (lengths[k+1] + lengths[k])/3
    W[order-3][order-3] = (lengths[order-2] + lengths[order-3])/3
    
    B = ma.array([(values[m] - values[m+1])/lengths[m] + (values[m+2] - values[m+1])/lengths[m+1] for m in range(order-2)])
    
    Q = dot(linalg.inv(W), B)
    M = None
    if diffOnEdges:
        M = ma.concatenate([[d2numFunction(points[0])], ma.copy(Q), [d2numFunction(points[order - 1])]])
    else:
        M = ma.concatenate([[0], ma.copy(Q), [0]])
    return M

def splinePoly(x, F, h, M, k, y):
    if k < 0 or k > len(M)-2:
        return 0
    else:
      return (M[k]*(x[k+1]-y)**3/(6*h[k])
          + M[k+1]*(y-x[k])**3/(6*h[k])
          + (F[k]-M[k]*h[k]**2/6)*(x[k+1]-y)/h[k]
          + (F[k+1]-M[k+1]*h[k]**2/6)*(y-x[k])/h[k])

def splinePolyDiff(x, F, h, M, k, y):
    if k < 0 or k > len(M)-2:
        return 0
    else:
      return (-M[k]*(x[k+1]-y)**2/(2*h[k])
          + M[k+1]*(y-x[k])**2/(2*h[k])
          + -(F[k]-M[k]*h[k]**2/6)/h[k]
          + (F[k+1]-M[k+1]*h[k]**2/6)/h[k])

def defineSpline(start, end, order, diffOnEdges=False):
    points = pylab.linspace(start, end, order)
    values = numFunction(points)
    
    lengths = [points[i+1] - points[i] for i in range(0, len(points) - 1)]
    
    M = calcM(points, values, lengths, diffOnEdges)
    maxK = len(M) - 2
    def spline(y): 
        k = int(floor((y - points[0])/lengths[0]))
        return splinePoly(points, values, lengths, M, k, y)
        
    def splineDiff(y):
        k = int(floor((y - points[0])/lengths[0]))
        return splinePolyDiff(points, values, lengths, M, k, y)
    
    return pylab.vectorize(spline), pylab.vectorize(splineDiff)

In [9]:
spline = None
results = []
for order in range(9, 200, 10):
    spline, splineDiff = defineSpline(-10, 10, order)
    spline1, spline1Diff = defineSpline(-10, 10, order, True)
    err = maximum(lambda x: abs(numFunction(x) - spline(x)), -10, 10)
    err1 = maximum(lambda x: abs(numFunction(x) - spline1(x)), -10, 10)
    derr = maximum(lambda x: abs(dnumFunction(x) - splineDiff(x)), -10, 10)
    derr1 = maximum(lambda x: abs(dnumFunction(x) - spline1Diff(x)), -10, 10)
    maxd4 = maximum(lambda x: abs(d4f(x)), -10, 10)
    tv1 = ((10. - (-10.))/order)**4*maxd4
    tv2 = ((10. - (-10.))/order)**3*maxd4
    results.append((err, err1, derr, derr1, tv1, tv2))
    
fig, axes = plt.subplots(figsize=(15,8))
axes.plot(t, spline(t))
DataFrame(results, index=range(9,200,10), columns=("ΔS1", "ΔS2", "dΔS1", "dΔS2", "h^(4-0)*max|f^(4)|", "h^(4-1)*max|f^(4)|"))


Out[9]:
ΔS1 ΔS2 dΔS1 dΔS2 h^(4-0)*max|f^(4)| h^(4-1)*max|f^(4)|
9 1.083913 1.083913 1.205524 1.305539 328.089555 147.640300
19 0.356945 0.356945 0.225878 0.225878 16.517642 15.691760
29 0.009946 0.009946 0.057141 0.057141 3.043480 4.413046
39 0.005689 0.005689 0.028893 0.028893 0.930474 1.814423
49 0.001932 0.001932 0.013667 0.013667 0.373403 0.914838
59 0.000739 0.000739 0.006167 0.006167 0.177646 0.524054
69 0.000065 0.000065 0.006975 0.006975 0.094966 0.327631
79 0.000154 0.000154 0.001855 0.001855 0.055265 0.218299
89 0.000102 0.000102 0.001167 0.001167 0.034309 0.152673
99 0.000067 0.000067 0.000980 0.000980 0.022409 0.110924
109 0.000041 0.000041 0.000736 0.000736 0.015250 0.083110
119 0.000028 0.000028 0.000564 0.000564 0.010734 0.063869
129 0.000065 0.000065 0.000378 0.000378 0.007773 0.050138
139 0.000014 0.000014 0.000346 0.000346 0.005766 0.040076
149 0.000011 0.000011 0.000181 0.000181 0.004367 0.032537
159 0.000009 0.000009 0.000152 0.000152 0.003368 0.026776
169 0.000005 0.000005 0.000182 0.000182 0.002639 0.022298
179 0.000004 0.000004 0.000241 0.000241 0.002097 0.018766
189 0.000003 0.000003 0.000129 0.000129 0.001687 0.015942
199 0.000003 0.000003 0.000109 0.000109 0.001373 0.013658