33import numpy as np
44from scipy .misc import central_diff_weights
55
6+ weights = np .zeros ((4 , 4 ))
7+ weights [0 , - 1 :] = np .array ([- 1 / 2 ])
8+ weights [1 , - 2 :] = np .array ([1 / 12 , - 2 / 3 ])
9+ weights [2 , - 3 :] = np .array ([- 1 / 60 , 3 / 20 , - 3 / 4 ])
10+ weights [3 , - 4 :] = np .array ([1 / 280 , - 4 / 105 , 1 / 5 , - 4 / 5 ])
11+
612
713def _derivative (_func , _xvar , _nacc ):
814 """ 1st derivative following central finite differencing
915 """
1016 derivative = np .zeros_like (_xvar )
1117 derivative [0 ] = (_func [1 ] - _func [0 ])/ (_xvar [1 ] - _xvar [0 ])
1218 derivative [- 1 ] = (_func [- 1 ] - _func [- 2 ])/ (_xvar [- 1 ] - _xvar [- 2 ])
13- weights = central_diff_weights (_nacc + 1 )
19+ _weights = central_diff_weights (_nacc + 1 )
1420
1521 for nac , idx in zip (range (2 , _nacc + 1 , 2 ), range (_nacc // 2 - 1 , - 1 , - 1 )):
1622 derivative [nac // 2 :- nac // 2 ] += (
17- weights [idx ]* _func [:- nac ] /
23+ _weights [idx ]* _func [:- nac ] /
1824 ((_xvar [nac :] - _xvar [:- nac ]) / float (nac )) +
19- weights [- idx - 1 ]* _func [nac :] /
25+ _weights [- idx - 1 ]* _func [nac :] /
2026 ((_xvar [nac :] - _xvar [:- nac ]) / float (nac )))
2127
2228 if _nacc > 2 :
@@ -26,6 +32,30 @@ def _derivative(_func, _xvar, _nacc):
2632 return derivative
2733
2834
35+ def acc4_derivative (_func , _xvar , _nacc = 4 ):
36+ """ 1st derivative, central differencing, accuracy up to 4
37+ """
38+ derivative = np .zeros_like (_xvar )
39+ derivative [0 ] = (_func [1 ] - _func [0 ])/ (_xvar [1 ] - _xvar [0 ])
40+ derivative [- 1 ] = (_func [- 1 ] - _func [- 2 ])/ (_xvar [- 1 ] - _xvar [- 2 ])
41+
42+ for nac , idx in zip (range (2 , _nacc + 1 , 2 ), range (_nacc // 2 )):
43+
44+ derivative [nac // 2 ] += (
45+ weights [nac // 2 - 1 , - idx - 1 ]* (_func [0 ] - _func [nac ]) /
46+ ((_xvar [nac ] - _xvar [0 ]) / float (nac )))
47+
48+ derivative [- nac // 2 - 1 ] += (
49+ weights [nac // 2 - 1 , - idx - 1 ]* (_func [- nac - 1 ] - _func [- 1 ]) /
50+ ((_xvar [- 1 ] - _xvar [- nac - 1 ]) / float (nac )))
51+
52+ derivative [nac // 2 + 1 :- nac // 2 - 1 ] += (
53+ weights [_nacc // 2 - 1 , - idx - 1 ]* (_func [1 :- nac - 1 ] - _func [nac + 1 :- 1 ]) /
54+ ((_xvar [nac + 1 :- 1 ] - _xvar [1 :- nac - 1 ]) / float (nac )))
55+
56+ return derivative
57+
58+
2959def acc_derivative (func , xvar , nacc ):
3060 """ 1st derivative of a _func wrt _xvar with _nacc accuracy
3161
@@ -40,15 +70,15 @@ def acc_derivative(func, xvar, nacc):
4070 NOTES:
4171 minor bug necessitates repeating calculation if nacc > 2
4272 """
43- if nacc = = 0 or nacc % 2 == 1 :
73+ if nacc < = 0 or nacc % 2 == 1 :
4474 raise ValueError ("n must be positive even" )
4575
76+ if nacc < 6 :
77+ return acc4_derivative (func , xvar , nacc )
78+
4679 axx_derivative = np .zeros_like (xvar )
4780 axx_derivative = _derivative (func , xvar , 2 )
4881
49- if nacc == 2 :
50- return axx_derivative
51-
5282 for nax in range (4 , nacc + 1 , 2 ):
5383 derivative = _derivative (func , xvar , nax )
5484 nan_idx = np .isnan (derivative )
0 commit comments