-
Notifications
You must be signed in to change notification settings - Fork 0
/
isochronism.py
70 lines (58 loc) · 2.34 KB
/
isochronism.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
import numpy as np
import numpy.polynomial.polynomial as Poly
from scipy.integrate import quad
class BalanceSpring:
def __init__(self, inertia, datafile, options={}):
'''
AVAILABLE OPTIONS :
'angle unit': 'rad', 'deg'
'data type': 'moment', 'potential'
'delimiter': any character
'polynomial degree': any positive integer
'''
self.options = { 'angle unit': 'rad', \
'delimiter': None, \
'polynomial degree': 9, \
'data type': 'moment' }
for key in options:
self.options[key] = options[key]
self.inertia = inertia
data = np.loadtxt(datafile, delimiter=self.options['delimiter'])
if self.options['angle unit'] == 'deg':
data[:,0] *= np.pi / 180.
self.deg = self.options['polynomial degree']
if self.options['data type'] == 'moment':
temp = Poly.polyfit(data[:,0], data[:,1], self.deg-1)
self.VPoly = Poly.polyint(temp)
elif self.options['data type'] == 'potential':
self.VPoly = Poly.polyfit(data[:,0], data[:,1], self.deg)
self.VPoly[0] = 0
self.VPoly[1] = 0
self.frequency = np.vectorize(self.frequency1)
def amplitude(self, energy):
# we compute the 2 real roots closest to 0
righthandside = np.zeros(self.deg+1)
righthandside[0] = energy
roots = Poly.polyroots(self.VPoly-righthandside)
rplus = np.inf
rminus = -np.inf
for r in np.real(roots[np.isreal(roots)]):
if r > 0 and r < rplus:
rplus = r
elif r < 0 and r > rminus:
rminus = r
return [rminus, rplus]
def amplitude_positive(self, energy):
temp, _ = self.amplitude(energy)
return temp
def frequency1(self, energy):
x1, x2 = self.amplitude(energy)
def f(x):
return 1. / np.sqrt( energy-Poly.polyval(x, self.VPoly) )
integral = quad(f, x1, x2)
return 1. / ( np.sqrt(2*self.inertia) * integral[0] )
def angle_with_unit(self, angle_in_rad):
if self.options['angle unit'] == 'rad':
return angle_in_rad
elif self.options['angle unit'] == 'deg':
return angle_in_rad * np.pi / 180.