Skip to content

Commit 9ee29a1

Browse files
author
Paul Miles
authored
Merge pull request #5 from prmiles/extend_precision
Extend precision
2 parents b4960fd + 5de36f7 commit 9ee29a1

File tree

4 files changed

+117
-23
lines changed

4 files changed

+117
-23
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
__pycache__
22
*.spyproject
3-
3+
*.coverage

pyfod/GaussLaguerre.py

+62-14
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,26 @@
88

99
import numpy as np
1010
import sys
11+
from sympy.integrals.quadrature import gauss_gen_laguerre as sp_gauss_laguerre
12+
import sympy as sp
1113

1214

1315
class GaussLaguerre:
1416

15-
def __init__(self, N=5, start=0.0, finish=1.0, alpha=0.0, f=None):
17+
def __init__(self, N=5, start=0.0, finish=1.0, alpha=0.0,
18+
f=None, extend_precision=True, n_digits=30):
1619
self.description = 'Gaussian-Laguerre Quadrature'
17-
points, weights = np.polynomial.laguerre.laggauss(deg=N)
18-
self.points = 1 - np.exp(-points)
20+
if extend_precision is False:
21+
points, weights = np.polynomial.laguerre.laggauss(deg=N)
22+
self.points = 1 - np.exp(-points)
23+
else:
24+
points, weights = sp_gauss_laguerre(
25+
n=N, n_digits=n_digits, alpha=0)
26+
points = [-p for p in points]
27+
points = sp.Array(points)
28+
self.points = sp.Array(
29+
np.ones(shape=len(points))) - points.applyfunc(sp.exp)
30+
weights = sp.Array(weights)
1931
self.weights = weights
2032
self.start = start
2133
self.finish = finish
@@ -31,23 +43,59 @@ def integrate(self, f=None, alpha=None):
3143
sys.exit('No function defined... provide function f')
3244
# transform kernel
3345
span = self.finish - self.start
34-
return (self.weights*(span**(1-alpha)*f(span*self.points
35-
+ self.start)*(1-self.points)**(-alpha))).sum()
46+
# check if sympy
47+
if isinstance(self.points, sp.Array):
48+
evalpoints = self.points.applyfunc(
49+
lambda x: span*x + self.start)
50+
feval = evalpoints.applyfunc(f)
51+
coef = self.points.applyfunc(
52+
lambda x: span**(1-alpha)*(1-x)**(-alpha))
53+
s = 0
54+
for ii, (w, f, t) in enumerate(zip(self.weights, feval, coef)):
55+
s += w*f*t
56+
return s
57+
else:
58+
coef = span**(1-alpha)*(1-self.points)**(-alpha)
59+
s = (self.weights*(coef*f(span*self.points + self.start))).sum()
60+
return s
3661

3762

3863
if __name__ == '__main__': # pragma: no cover
3964

40-
def f(t):
41-
return np.cos(2*t)
65+
n_digits = 50
66+
alpha = 0.9
67+
start = 0.0
68+
finish = 1.0
69+
dt = 1e-6
70+
N = 24
4271

43-
GLag = GaussLaguerre(N=100, start=1.0, finish=12.0)
72+
def fcosnp(x):
73+
return np.cos(2*x) + 3
4474

45-
a = GLag.integrate(f)
46-
print('a = {}'.format(a))
75+
GLag = GaussLaguerre(N=N, start=start, finish=finish,
76+
f=fcosnp, alpha=0, extend_precision=False)
77+
F1 = GLag.integrate()
78+
print('Int(cos(2t)+3) = {} ({})'.format(F1, 3.4546))
79+
80+
def fexp(x):
81+
return sp.exp(2*x)
82+
GLag = GaussLaguerre(N=N, start=start, finish=finish,
83+
f=fexp, alpha=alpha, n_digits=n_digits)
84+
F1 = GLag.integrate()
85+
GLag = GaussLaguerre(N=N, start=start, finish=finish-dt,
86+
f=fexp, alpha=alpha, n_digits=n_digits)
87+
F2 = GLag.integrate()
88+
print('D[f(t)=exp(2t)] = {} ({})'.format(
89+
(F1-F2)/(dt*sp.gamma(1-0.9)), 13.815))
90+
91+
def fcos(x):
92+
return sp.cos(2*x)
4793

48-
GLag = GaussLaguerre(N=8, start=0.0, finish=1.0, f=f, alpha=0.9)
94+
GLag = GaussLaguerre(N=N, start=start, finish=finish,
95+
f=fcos, alpha=alpha, n_digits=n_digits)
4996
F1 = GLag.integrate()
50-
dt = 1e-4
51-
GLag = GaussLaguerre(N=8, start=0.0, finish=1.0-dt, f=f, alpha=0.9)
97+
GLag = GaussLaguerre(N=N, start=start, finish=finish-dt,
98+
f=fcos, alpha=alpha, n_digits=n_digits)
5299
F2 = GLag.integrate()
53-
print('D[f(t)] = {}'.format((F1-F2)/dt))
100+
print('D[f(t)=cos(2t)] = {} ({})'.format(
101+
(F1-F2)/(dt*sp.gamma(1-0.9)), -1.779))

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
numpy>=1.14
22
scipy>=1.0
3+
sympy>=1.3
34
coveralls

test/test_GaussLaguerre.py

+53-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@author: prmiles
66
"""
77

8+
import sympy as sp
89
import numpy as np
910
import unittest
1011
from pyfod.GaussLaguerre import GaussLaguerre
@@ -13,12 +14,15 @@
1314
def f(t):
1415
return np.cos(t)
1516

17+
def fsp(t):
18+
return sp.cos(t)
19+
1620

1721
# --------------------------
18-
class Initialization(unittest.TestCase):
22+
class Initialization_non_extended(unittest.TestCase):
1923

2024
def test_init(self):
21-
GQ = GaussLaguerre(N=10, start=1.0, finish=12.0)
25+
GQ = GaussLaguerre(N=10, start=1.0, finish=12.0, extend_precision=False)
2226
self.assertTrue(hasattr(GQ, 'f'), msg='Expect attribute f to exist')
2327
self.assertEqual(GQ.f, None, msg='Expect value of None')
2428
self.assertEqual(GQ.points.size, 10, msg='Expect 10 nodes')
@@ -28,7 +32,7 @@ def test_init(self):
2832

2933
def test_init_with_f(self):
3034

31-
GQ = GaussLaguerre(N=10, start=1.0, finish=12.0, alpha=0.5, f=f)
35+
GQ = GaussLaguerre(N=10, start=1.0, finish=12.0, alpha=0.5, f=f, extend_precision=False)
3236
self.assertTrue(hasattr(GQ, 'f'), msg='Expect attribute f to exist')
3337
self.assertEqual(GQ.f, f, msg='Expect function f')
3438
self.assertEqual(GQ.points.size, 10, msg='Expect 10 nodes')
@@ -37,19 +41,60 @@ def test_init_with_f(self):
3741

3842

3943
# --------------------------
40-
class Integrate(unittest.TestCase):
44+
class Initialization_with_extended(unittest.TestCase):
45+
46+
def test_init(self):
47+
GQ = GaussLaguerre(N=10, start=1.0, finish=12.0)
48+
self.assertTrue(hasattr(GQ, 'f'), msg='Expect attribute f to exist')
49+
self.assertEqual(GQ.f, None, msg='Expect value of None')
50+
self.assertEqual(len(GQ.points), 10, msg='Expect 10 nodes')
51+
self.assertEqual(len(GQ.weights), 10, msg='Expect 10 weights')
52+
self.assertEqual(GQ.alpha, 0, msg='Expect alpha eq 0')
53+
54+
55+
def test_init_with_f(self):
56+
57+
GQ = GaussLaguerre(N=10, start=1.0, finish=12.0, alpha=0.5, f=fsp)
58+
self.assertTrue(hasattr(GQ, 'f'), msg='Expect attribute f to exist')
59+
self.assertEqual(GQ.f, fsp, msg='Expect function fsp')
60+
self.assertEqual(len(GQ.points), 10, msg='Expect 10 nodes')
61+
self.assertEqual(len(GQ.weights), 10, msg='Expect 10 weights')
62+
self.assertEqual(GQ.alpha, 0.5, msg='Expect alpha eq 0.5')
63+
64+
65+
# --------------------------
66+
class Integrate_non_extended(unittest.TestCase):
4167

4268
def test_no_f(self):
43-
GQ = GaussLaguerre()
69+
GQ = GaussLaguerre(extend_precision=False)
4470
with self.assertRaises(SystemExit):
4571
GQ.integrate()
4672

4773
def test_with_f(self):
48-
GQ = GaussLaguerre()
74+
GQ = GaussLaguerre(extend_precision=False)
4975
a = GQ.integrate(f=f)
5076
self.assertEqual(a.size, 1, msg='Expect float return')
5177

5278
def test_with_alpha(self):
53-
GQ = GaussLaguerre()
79+
GQ = GaussLaguerre(extend_precision=False)
5480
a = GQ.integrate(f=f, alpha=0.5)
55-
self.assertEqual(a.size, 1, msg='Expect float return')
81+
self.assertEqual(a.size, 1, msg='Expect float return')
82+
83+
84+
# --------------------------
85+
class Integrate_with_extended(unittest.TestCase):
86+
87+
def test_no_f(self):
88+
GQ = GaussLaguerre()
89+
with self.assertRaises(SystemExit):
90+
GQ.integrate()
91+
92+
def test_with_f(self):
93+
GQ = GaussLaguerre()
94+
a = GQ.integrate(f=fsp)
95+
self.assertTrue(a.is_Float, msg='Expect float return')
96+
97+
def test_with_alpha(self):
98+
GQ = GaussLaguerre()
99+
a = GQ.integrate(f=fsp, alpha=0.5)
100+
self.assertTrue(a.is_Float, msg='Expect float return')

0 commit comments

Comments
 (0)