-
Notifications
You must be signed in to change notification settings - Fork 5
/
clenshaw_curtis_constants.py
111 lines (96 loc) · 2.7 KB
/
clenshaw_curtis_constants.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# http://www.sam.math.ethz.ch/~waldvoge/Papers/fejer.pdf
import numpy as np
# 2.4
def weights(n):
n -= 1
v = np.linspace(1, 0, n + 1) * np.pi
j = np.array(range(1, n / 2 + 1))[:, None]
b = 2. * np.ones(j.shape)
b -= (j == n / 2.)
c = 2 * np.ones(v.shape)
c[0] -= 1
c[-1] -= 1
s = (b / (4. * j ** 2 - 1) * np.cos(2 * j * v)).sum(0)
x = (np.cos(v) + 1.0) - 1.0
w = c / n * (1. - s)
assert np.abs(w[0] - 1. / (n ** 2. - 1. + (n % 2))) < 1e-12
assert np.abs(w[-1] - 1. / (n ** 2. - 1. + (n % 2))) < 1e-12
return x, w
def test_with_sympy(n):
import sympy
a, b, c, x = sympy.symbols("a, b, c, x")
f = a * x ** 2 + b * x + c
print sum([w * f.subs(x, xi) for xi, w in zip(*weights(n))])
print sympy.integrate(f, (x, -1, 1))
def clencurt(n1):
""" Computes the Clenshaw Curtis nodes and weights """
# http://www.scientificpython.net/pyblog/clenshaw-curtis-quadrature
if n1 == 1:
x = 0.
w = 2.
if n1 == 2:
x = [-1., 1.]
w = [1., 1.]
else:
n = n1 - 1
C = np.zeros((n1, 2))
k = 2 * (1 + np.arange(np.floor(n / 2)))
C[::2, 0] = 2 / np.hstack((1, 1 - k * k))
C[1, 1] = -n
V = np.vstack((C, np.flipud(C[1:n, :])))
F = np.real(np.fft.ifft(V, n=None, axis=0))
x = F[0:n1, 1]
w = np.hstack((F[0, 0], 2 * F[1:n, 0], F[n, 0]))
return x, w
def values(i):
n = 2 ** i
if n >= 1:
yield n / 2
if n >= 3:
yield 0
yield n
h = n / 2
while h >= 2:
k = h / 2
while k <= n:
yield k
k += h
h /= 2
def haft_values(i):
n = 2 ** i
if n >= 1:
yield n / 2
if n >= 3:
yield n
h = n / 2
while h >= 2:
k = h / 2 + n / 2
while k <= n:
yield k
k += h
h /= 2
max_i = 8
print "pub const ABCISSAS: &'static [f64] = &", list(weights(2 ** max_i + 1)[0][list(haft_values(max_i))]), ";"
print "pub const WEIGHTS: [&'static [f64];", max_i - 1, "] = ["
for w in [weights(2 ** i + 1)[1][list(haft_values(i))] for i in range(2, max_i + 1)]:
print "&", list(w), ","
print "];"
for i in range(1, 5):
n = 2 ** i + 1
o_x = weights(n)[0][n / 2:]
o_w = weights(n)[1][n / 2:]
print "o_x", n, o_x
print "o_w", n, o_w
n = 2 ** (i + 1) + 1
n_x = weights(n)[0][n / 2:]
n_w = weights(n)[1][n / 2:]
print "n_x", n, n_x
print "n_w", n, n_w
on_x = n_x[::2]
on_w = n_w[::2]
print "on_x", n, on_x
print "on_w", n, on_w
print "on_w/o_w", n, on_w / o_w
# on_w/o_w is not a constant so we do need to hold the old f calls
# looks like we can reuse x's but not w's
print