-
Notifications
You must be signed in to change notification settings - Fork 6
/
differentiation.py
93 lines (73 loc) · 3.02 KB
/
differentiation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
###############################################################################
#
# CSCI 4446 - Chaotic Dynamics
#
# File: differentiation.py
# Author: Ken Sheedlo
#
# Numerical differentiation routines.
#
###############################################################################
from __future__ import division
import numpy
import chaostest
import unittest
def ndiff(ts, xs):
'''
Computes the numerical derivative over arbitrary data with O(h^2) error.
Where h is the spacing of the ts, this function uses a 3-point formula to
compute dx/dt. t-values do not have to be evenly spaced. ts must have length
at least 3.
Source: Burden and Faires. Numerical Analysis, 8th edition. Chapter 4.1,
"Numerical Differentiation".
Params:
ts Time values for each data point.
xs X values for each data point. Must have the same length as ts.
Returns: dxs a ndarray with the value of the derivative at each t.
'''
def _diff(ts, xs):
return xs[0]*(ts[1]-ts[2])/((ts[0]-ts[1])*(ts[0]-ts[2])) + \
xs[1]*(2*ts[1]-ts[0]-ts[2])/((ts[1]-ts[0])*(ts[1]-ts[2])) + \
xs[2]*(ts[1]-ts[0])/((ts[2]-ts[0])*(ts[2]-ts[1]))
ts_len = len(ts)
dxs = numpy.empty(ts_len, dtype=numpy.float64)
dxs[0] = xs[0]*(2*ts[0]-ts[1]-ts[2])/((ts[0]-ts[1])*(ts[0]-ts[2])) + \
xs[1]*(ts[0]-ts[2])/((ts[1]-ts[0])*(ts[1]-ts[2])) + \
xs[2]*(ts[0]-ts[1])/((ts[2]-ts[0])*(ts[2]-ts[1]))
for i in xrange(1, ts_len-1):
dxs[i] = _diff(ts[i-1:i+2], xs[i-1:i+2])
dxs[-1] = xs[-3]*(ts[-1]-ts[-2])/((ts[-3]-ts[-2])*(ts[-3]-ts[-1])) + \
xs[-2]*(ts[-1]-ts[-3])/((ts[-2]-ts[-3])*(ts[-2]-ts[-1])) + \
xs[-1]*(2*ts[-1]-ts[-3]-ts[-2])/((ts[-1]-ts[-3])*(ts[-1]-ts[-2]))
return dxs
def ddiff(ts, xs):
'''
Computes the numerical derivative using divided differences.
This function is less accurate than ndiff above. It has O(h) error and uses
a simpler formula. It is mainly useful for debugging problems with the more
complicated ndiff. ts and xs must have length at least 2.
Params:
ts Time values for each data point.
xs X values for each data point. Must have the same length as ts.
Returns: dxs a ndarray with the value of the derivative at each t.
'''
ts_len = len(ts)
dxs = numpy.empty(ts_len, dtype=numpy.float64)
for i in xrange(ts_len-1):
dxs[i] = (xs[i+1]-xs[i])/(ts[i+1]-ts[i])
dxs[-1] = dxs[-2]
return dxs
class TestDifferentiation(chaostest.TestCase):
'''
Test suite for numerical differentiators.
'''
def test_ndiff(self):
'''
Tests the general numerical differentiator for correctness.
'''
ts = 0.01 * numpy.array(range(100), dtype=numpy.float64)
xs = numpy.array([(t**2) for t in ts], dtype=numpy.float64)
expected = 0.02 * numpy.array(range(100), dtype=numpy.float64)
self.assertArrayEqual(ndiff(ts, xs), expected, places=4)
if __name__ == "__main__":
unittest.main()