ruspectroscopy-tools 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ruspectroscopy_tools-0.0.1/LICENSE +21 -0
- ruspectroscopy_tools-0.0.1/PKG-INFO +53 -0
- ruspectroscopy_tools-0.0.1/README.md +38 -0
- ruspectroscopy_tools-0.0.1/pyproject.toml +3 -0
- ruspectroscopy_tools-0.0.1/rusmodules/__init__.py +0 -0
- ruspectroscopy_tools-0.0.1/rusmodules/compile_data_generator.py +49 -0
- ruspectroscopy_tools-0.0.1/rusmodules/compile_rus_module.py +208 -0
- ruspectroscopy_tools-0.0.1/rusmodules/rus.c +361 -0
- ruspectroscopy_tools-0.0.1/ruspectroscopy_tools.egg-info/PKG-INFO +53 -0
- ruspectroscopy_tools-0.0.1/ruspectroscopy_tools.egg-info/SOURCES.txt +12 -0
- ruspectroscopy_tools-0.0.1/ruspectroscopy_tools.egg-info/dependency_links.txt +1 -0
- ruspectroscopy_tools-0.0.1/ruspectroscopy_tools.egg-info/top_level.txt +1 -0
- ruspectroscopy_tools-0.0.1/setup.cfg +4 -0
- ruspectroscopy_tools-0.0.1/setup.py +35 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 jacubillos10
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ruspectroscopy_tools
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A simple tool that generates Gamma matrix and E matrix, given the elastic constants, mass, dimansions and shape of a sample, in Resonant Ultrasound Spectroscopy. Use scipy.linalg.eigh(...) to solve the forward problem
|
|
5
|
+
Home-page: https://github.com/jacubillos10/RUSpectroscopy_Tools
|
|
6
|
+
Author: Alejandro Cubillos
|
|
7
|
+
Author-email: alejandro4cm@outlook.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
|
|
16
|
+
# RUSpectroscopy_tools
|
|
17
|
+
|
|
18
|
+
A C extension module for generating Gamma and Epsilon matrices, in Resonant Ultrasound Spectroscopy.
|
|
19
|
+
|
|
20
|
+
## Authors
|
|
21
|
+
|
|
22
|
+
- Alejandro Cubillos - alejandro4cm@outlook.com
|
|
23
|
+
- Manuela Rivas
|
|
24
|
+
- Julián Rincón
|
|
25
|
+
|
|
26
|
+
## Import:
|
|
27
|
+
```python
|
|
28
|
+
from rusmodules import rus
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage Example
|
|
32
|
+
```python
|
|
33
|
+
gamma = rus.gamma_matrix(N, C, geometry, shape)
|
|
34
|
+
E = rus.E_matrix(N, shape)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
# Where:
|
|
38
|
+
* N <int> represents the maximim grade of the polynomials of the basis functions
|
|
39
|
+
* C <np.array> 6x6 matrix with the elastic constants
|
|
40
|
+
* geometry <np.array> (3,) shape array containing the dimensions of the sample
|
|
41
|
+
* shape <int> 0 for parallelepiped, 1 for cylinder and 2 to spheroid
|
|
42
|
+
|
|
43
|
+
Solve forward problem with scipy:
|
|
44
|
+
Eigenvalues return $m\omega^2$
|
|
45
|
+
```python
|
|
46
|
+
eigenvals, eigenvects = scipy.linalg.eigh(a = gamma, b = E)
|
|
47
|
+
omega = (eigenvals[6:]/m)**(1/2) #remember the fisrt 6 eigenvalues must be near zero
|
|
48
|
+
frequencies = omega/(2*np.pi)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Installation:
|
|
52
|
+
```bash
|
|
53
|
+
pip3 install ruspectroscopy_tools
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# RUSpectroscopy_tools
|
|
2
|
+
|
|
3
|
+
A C extension module for generating Gamma and Epsilon matrices, in Resonant Ultrasound Spectroscopy.
|
|
4
|
+
|
|
5
|
+
## Authors
|
|
6
|
+
|
|
7
|
+
- Alejandro Cubillos - alejandro4cm@outlook.com
|
|
8
|
+
- Manuela Rivas
|
|
9
|
+
- Julián Rincón
|
|
10
|
+
|
|
11
|
+
## Import:
|
|
12
|
+
```python
|
|
13
|
+
from rusmodules import rus
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage Example
|
|
17
|
+
```python
|
|
18
|
+
gamma = rus.gamma_matrix(N, C, geometry, shape)
|
|
19
|
+
E = rus.E_matrix(N, shape)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
# Where:
|
|
23
|
+
* N <int> represents the maximim grade of the polynomials of the basis functions
|
|
24
|
+
* C <np.array> 6x6 matrix with the elastic constants
|
|
25
|
+
* geometry <np.array> (3,) shape array containing the dimensions of the sample
|
|
26
|
+
* shape <int> 0 for parallelepiped, 1 for cylinder and 2 to spheroid
|
|
27
|
+
|
|
28
|
+
Solve forward problem with scipy:
|
|
29
|
+
Eigenvalues return $m\omega^2$
|
|
30
|
+
```python
|
|
31
|
+
eigenvals, eigenvects = scipy.linalg.eigh(a = gamma, b = E)
|
|
32
|
+
omega = (eigenvals[6:]/m)**(1/2) #remember the fisrt 6 eigenvalues must be near zero
|
|
33
|
+
frequencies = omega/(2*np.pi)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Installation:
|
|
37
|
+
```bash
|
|
38
|
+
pip3 install ruspectroscopy_tools
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from numba import njit, types
|
|
3
|
+
from numba.pycc import CC
|
|
4
|
+
cc = CC('data_generator')
|
|
5
|
+
|
|
6
|
+
@njit("f8[:,:](f8,f8,i8)")
|
|
7
|
+
@cc.export("generate_C_matrix", "f8[:,:](f8,f8,i8)")
|
|
8
|
+
def generate_C_matrix(C_min, C_max, crystal_structure):
|
|
9
|
+
C = np.zeros((6,6))
|
|
10
|
+
C_prc = np.zeros(3)
|
|
11
|
+
C_sec = np.zeros(6)
|
|
12
|
+
C_ter = np.zeros(12)
|
|
13
|
+
d_struc = np.array([[3,6],[2,4],[1,2],[1,1]])
|
|
14
|
+
n_p = d_struc[crystal_structure,0]
|
|
15
|
+
n_s = d_struc[crystal_structure,1]
|
|
16
|
+
C_prc_raw = np.random.uniform(C_min, C_max, n_p)
|
|
17
|
+
C_max_sec = 0.5*min(C_prc)
|
|
18
|
+
C_sec_raw = np.random.uniform(C_min, C_max_sec, n_s)
|
|
19
|
+
if crystal_structure == 1:
|
|
20
|
+
C_prc[0:2] = C_prc_raw[0]
|
|
21
|
+
C_prc[2] = C_prc_raw[1]
|
|
22
|
+
C_sec[0] = C_sec_raw[0]
|
|
23
|
+
C_sec[1:3] = C_sec_raw[1]
|
|
24
|
+
C_sec[3:5] = C_sec_raw[2]
|
|
25
|
+
C_sec[5] = C_sec_raw[3]
|
|
26
|
+
elif crystal_structure == 2:
|
|
27
|
+
C_prc[:] = C_prc_raw[0]
|
|
28
|
+
C_sec[0:3] = C_sec_raw[0]
|
|
29
|
+
C_sec[3:] = C_sec_raw[1]
|
|
30
|
+
elif crystal_structure == 3:
|
|
31
|
+
C_prc[:] = C_prc_raw[0]
|
|
32
|
+
C_sec[0:3] = C_prc_raw[0] - 2*C_sec_raw[0]
|
|
33
|
+
C_sec[3:] = C_sec_raw[0]
|
|
34
|
+
else:
|
|
35
|
+
C_prc = C_prc_raw
|
|
36
|
+
C_sec = C_sec_raw
|
|
37
|
+
#end if
|
|
38
|
+
for i in range(3):
|
|
39
|
+
for j in range(3):
|
|
40
|
+
C[i,j] = C_prc[i] if i == j else C_sec[i+j-1]
|
|
41
|
+
C[i+3,j+3] = C_sec[i+3] if i == j else 0
|
|
42
|
+
#fin for
|
|
43
|
+
#fin if
|
|
44
|
+
|
|
45
|
+
return C
|
|
46
|
+
#end function
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
cc.compile()
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from numba import njit, types
|
|
3
|
+
from numba.pycc import CC
|
|
4
|
+
|
|
5
|
+
cc = CC('rus_old')
|
|
6
|
+
@njit("f8(i8)")
|
|
7
|
+
@cc.export("fact2", "f8(i8)")
|
|
8
|
+
def fact2(N):
|
|
9
|
+
if N < -1:
|
|
10
|
+
raise ArithmeticError("Está entrando en el doble factorial un númerno menor a -1")
|
|
11
|
+
elif (N == 0 or N == -1 or N == 1):
|
|
12
|
+
return 1
|
|
13
|
+
else:
|
|
14
|
+
prod = 1.0
|
|
15
|
+
for i in range(N,1,-2):
|
|
16
|
+
prod = prod*i
|
|
17
|
+
#fin for
|
|
18
|
+
return prod
|
|
19
|
+
#fin if
|
|
20
|
+
#fin función
|
|
21
|
+
|
|
22
|
+
@njit("i8(i8,i8)")
|
|
23
|
+
@cc.export("it_c", "i8(i8,i8)")
|
|
24
|
+
def it_c(i,j):
|
|
25
|
+
"""
|
|
26
|
+
This function changes the double index convention for single index convention in the elastic constant matrix C.
|
|
27
|
+
00 is changed to 0, 11 is changed to 1, 22 is changed to 2,
|
|
28
|
+
01 or 10 is changed to 5
|
|
29
|
+
02 or 20 is changed to 4
|
|
30
|
+
12 or 21 is changed to 3
|
|
31
|
+
|
|
32
|
+
@Input i <int>: first index to be changed
|
|
33
|
+
@Input j <int>: second index to be changed
|
|
34
|
+
@Return index <int>: New index
|
|
35
|
+
"""
|
|
36
|
+
if i == j:
|
|
37
|
+
index = i
|
|
38
|
+
else:
|
|
39
|
+
index = 6 - (i + j)
|
|
40
|
+
#fin if
|
|
41
|
+
return index
|
|
42
|
+
#fin función
|
|
43
|
+
|
|
44
|
+
@njit("f8(i8[:],i8[:],i8,i8,i8,i8,f8[:,:],f8[:],i8)")
|
|
45
|
+
@cc.export("generate_term_in_gamma_matrix_element", "f8(i8[:],i8[:],i8,i8,i8,i8,f8[:,:],f8[:],i8)")
|
|
46
|
+
def generate_term_in_ſ(exp_index1, exp_index2, i1, i2, j1, j2, C, geo_par, options):
|
|
47
|
+
"""
|
|
48
|
+
This function generates one term of the sum composing an element of the matrix ſ. See equation 11 in Leisure 1997. Be sure geo_par
|
|
49
|
+
to be an array of floats NOT INTEGERS!!
|
|
50
|
+
@Input exp_index1 <np.array>: Exponents lambda, mu and nu of the p element in the matrix and i1 index
|
|
51
|
+
@Input exp_index2 <np.array>: Exponents lambda, mu and nu of the q element in the matrix and i2 index
|
|
52
|
+
@Input i1 <int>: index i of the expresion in eq 11. 0 to x, 1 to y, 2 to z
|
|
53
|
+
@Input i2 <int>: index i' of the expresion in eq 11. 0 to x, 1 to y, 2 to z
|
|
54
|
+
@Input j1 <int>: index j of the sum in equation 11. 0 to x, 1 to y, 2 to z
|
|
55
|
+
@Input j2 <int>: index j' of the sum in equation 11. 0 to x, 1 to y, 2 to z
|
|
56
|
+
@Input C <np.array>: Matrix with the elastic constants
|
|
57
|
+
@Input geo_par <np.array>: Geometric parameters of the sample, such as Lx, Ly, Lz. Be sure to enter a array of floats NOT INTEGERS!
|
|
58
|
+
@Return <float>: Returns a term in the equation 11 of Leisure 1997
|
|
59
|
+
"""
|
|
60
|
+
array_j1 = np.zeros(3)
|
|
61
|
+
array_j2 = np.zeros(3)
|
|
62
|
+
array_j1[j1] = 1
|
|
63
|
+
array_j2[j2] = 1
|
|
64
|
+
coeff = exp_index1 + exp_index2 + 1 - array_j1 - array_j2
|
|
65
|
+
Q = (1 - (-1)**coeff[0])*(1 - (-1)**coeff[1])*(1 - (-1)**coeff[2])
|
|
66
|
+
S = exp_index1[j1]*exp_index2[j2]
|
|
67
|
+
#geo_par = np.array(geo_par, dtype = float)
|
|
68
|
+
if Q == 0 or S == 0:
|
|
69
|
+
return 0
|
|
70
|
+
#fin if
|
|
71
|
+
if options == 1:
|
|
72
|
+
R = (fact2(coeff[0] - 2)*fact2(coeff[1] - 2))/(fact2(coeff[0] + coeff[1])*coeff[2])
|
|
73
|
+
alpha = np.pi/4
|
|
74
|
+
elif options == 2:
|
|
75
|
+
R = (fact2(coeff[0] - 2)*fact2(coeff[1] - 2)*fact2(coeff[2] - 2))/(fact2(sum(coeff)))
|
|
76
|
+
alpha = np.pi/6
|
|
77
|
+
else:
|
|
78
|
+
R = 1/(coeff[0]*coeff[1]*coeff[2])
|
|
79
|
+
alpha = 1
|
|
80
|
+
#fin if
|
|
81
|
+
#P = 4*C[it_c(i1,j1),it_c(i2,j2)]/(geo_par[j1]*geo_par[j2])
|
|
82
|
+
if j1 == j2:
|
|
83
|
+
beta = np.prod(geo_par)/(geo_par[j1]**2)
|
|
84
|
+
else:
|
|
85
|
+
beta = geo_par[3-j1-j2]
|
|
86
|
+
#fin if
|
|
87
|
+
P = 4*alpha*C[it_c(i1,j1),it_c(i2,j2)]*beta
|
|
88
|
+
return P*Q*S*R
|
|
89
|
+
#fin función
|
|
90
|
+
|
|
91
|
+
@njit("f8(i8,i8,i8[:],i8[:],f8[:,:],f8[:],i8)")
|
|
92
|
+
@cc.export("generate_matrix_element_gamma", "f8(i8,i8,i8[:],i8[:],f8[:,:],f8[:],i8)")
|
|
93
|
+
def generate_matrix_element_ſ(i1, i2, exp_index1, exp_index2, C, geo_par, options):
|
|
94
|
+
"""
|
|
95
|
+
This function generates a matrix element of ſ, given two axis indexes (0 is x, 1 is y, 2 is z), two arrays of indexes which
|
|
96
|
+
Contain the exponents of the power series, the elastic constants and the geometric parameters
|
|
97
|
+
@Input i1 <int>: index i of the expresion in eq 11. 0 to x, 1 to y, 2 to z
|
|
98
|
+
@Input i2 <int>: index i' of the expresion in eq 11. 0 to x, 1 to y, 2 to z
|
|
99
|
+
@Input exp_index1 <np.array>: Exponents lambda, mu and nu of the p element in the matrix and i1 index
|
|
100
|
+
@Input exp_index2 <np.array>: Exponents lambda, mu and nu of the q element in the matrix and i2 index
|
|
101
|
+
@Input C <np.array>: Matrix with the elastic constants
|
|
102
|
+
@Input geo_par <np.array>: Geometric parameters of the sample, such as Lx, Ly, Lz. Be sure to enter a array of floats NOT INTEGERS!
|
|
103
|
+
@Return <float>: Returns a matrix element ſ
|
|
104
|
+
"""
|
|
105
|
+
acum = 0
|
|
106
|
+
for j1 in range(3):
|
|
107
|
+
for j2 in range(3):
|
|
108
|
+
acum += generate_term_in_ſ(exp_index1, exp_index2, i1, i2, j1, j2, C, geo_par, options)
|
|
109
|
+
# fin for
|
|
110
|
+
#fin for
|
|
111
|
+
return acum
|
|
112
|
+
#fin función
|
|
113
|
+
|
|
114
|
+
@njit("f8(i8,i8,i8[:],i8[:],i8)")
|
|
115
|
+
@cc.export("generate_matrix_element_E", "f8(i8,i8,i8[:],i8[:],i8)")
|
|
116
|
+
def generate_matrix_element_E(i1, i2, exp_index1, exp_index2, options):
|
|
117
|
+
"""
|
|
118
|
+
This function generates a matrix element of E, given two axis indexes (0 is x, 1 is y, 2 is z), two arrays of indexes which
|
|
119
|
+
contain the exponents of the power series, the elastic constants and the geometric parameters.
|
|
120
|
+
"""
|
|
121
|
+
if i1 != i2:
|
|
122
|
+
return 0
|
|
123
|
+
else:
|
|
124
|
+
coeff = exp_index1 + exp_index2 + 1
|
|
125
|
+
Q = (1 - (-1)**coeff[0])*(1 - (-1)**coeff[1])*(1 - (-1)**coeff[2])
|
|
126
|
+
if Q == 0:
|
|
127
|
+
return 0
|
|
128
|
+
#fin if
|
|
129
|
+
if options == 1:
|
|
130
|
+
R = (fact2(coeff[0] - 2)*fact2(coeff[1] - 2))/(fact2(coeff[0] + coeff[1])*coeff[2])
|
|
131
|
+
elif options == 2:
|
|
132
|
+
R = (fact2(coeff[0] - 2)*fact2(coeff[1] - 2)*fact2(coeff[2] - 2))/(fact2(sum(coeff)))
|
|
133
|
+
else:
|
|
134
|
+
R = 1/(coeff[0]*coeff[1]*coeff[2])
|
|
135
|
+
#fin if
|
|
136
|
+
#print("Numba coeff: ", coeff, " fact 0: ", fact2(coeff[0]), " fact 1: ", fact2(coeff[1]), " fact 2: ", fact2(coeff[2]))
|
|
137
|
+
#print("Operacion 1 numba: ", (fact2(coeff[0] - 2)*fact2(coeff[1] - 2)))
|
|
138
|
+
#print("Operacion 2 numba: ", (fact2(coeff[0] + coeff[1])*coeff[2]))
|
|
139
|
+
#print("numba's 35!!= ", fact2(35))
|
|
140
|
+
return Q*R
|
|
141
|
+
#fin if
|
|
142
|
+
#fin funcion
|
|
143
|
+
|
|
144
|
+
@njit("i8[:,:](i8)")
|
|
145
|
+
@cc.export("generate_combinations", "i8[:,:](i8)")
|
|
146
|
+
def generate_combinations(N):
|
|
147
|
+
R = int((1/6) * (N + 1) * (N + 2) * (N + 3))
|
|
148
|
+
combi = np.zeros((R,3), dtype=np.int64)
|
|
149
|
+
l = 0
|
|
150
|
+
for n in range(N + 1):
|
|
151
|
+
for i in range(n + 1):
|
|
152
|
+
for j in range(n + 1 - i):
|
|
153
|
+
k = n - i - j
|
|
154
|
+
combi[l,:] = np.array([i, j, k])
|
|
155
|
+
l += 1
|
|
156
|
+
#fin for
|
|
157
|
+
#fin for
|
|
158
|
+
return combi
|
|
159
|
+
#fin funcion
|
|
160
|
+
|
|
161
|
+
@cc.export("E_matrix", "f8[:,:](i8,i8)")
|
|
162
|
+
def E_matrix(N, options):
|
|
163
|
+
comb = generate_combinations(N)
|
|
164
|
+
R = len(comb[:,0])
|
|
165
|
+
E = np.zeros((3*R,3*R), dtype = np.float64)
|
|
166
|
+
for i in range(3):
|
|
167
|
+
for j in range(3):
|
|
168
|
+
for lm in range(R):
|
|
169
|
+
for lf in range(R):
|
|
170
|
+
exp_index1 = comb[lm,:]
|
|
171
|
+
exp_index2 = comb[lf,:]
|
|
172
|
+
E[(i*R + lm), (j*R + lf)] = generate_matrix_element_E(i, j, exp_index1, exp_index2, options)
|
|
173
|
+
#fin for
|
|
174
|
+
#fin for
|
|
175
|
+
#fin for
|
|
176
|
+
#fin for
|
|
177
|
+
return E
|
|
178
|
+
#fin función
|
|
179
|
+
|
|
180
|
+
@cc.export("gamma_matrix", "f8[:,:](i8,f8[:,:],f8[:],i8)")
|
|
181
|
+
def gamma_matrix(N, C, geo_par, options):
|
|
182
|
+
comb = generate_combinations(N)
|
|
183
|
+
R = len(comb[:,0])
|
|
184
|
+
gamma = np.zeros((3*R,3*R), dtype = np.float64)
|
|
185
|
+
for i in range(3):
|
|
186
|
+
for j in range(3):
|
|
187
|
+
for lm in range(R):
|
|
188
|
+
for lf in range(R):
|
|
189
|
+
exp_index1 = comb[lm,:]
|
|
190
|
+
exp_index2 = comb[lf,:]
|
|
191
|
+
gamma[(i*R + lm), (j*R + lf)] = generate_matrix_element_ſ(i, j, exp_index1, exp_index2, C, geo_par, options)
|
|
192
|
+
#fin for
|
|
193
|
+
#fin for
|
|
194
|
+
#fin for
|
|
195
|
+
#fin for
|
|
196
|
+
#print("Hello from numba")
|
|
197
|
+
return gamma
|
|
198
|
+
#fin función
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
if __name__ == "__main__":
|
|
202
|
+
cc.compile()
|
|
203
|
+
#C_const = np.genfromtxt('constantes.csv', delimiter=',', skip_header=0, dtype=float)
|
|
204
|
+
#aa = generate_term_in_ſ(np.array([1, 0, 0]), np.array([0, 0, 1]), 0, 1, 0, 2, C_const, np.array([1.0, 1.0, 1.0]))
|
|
205
|
+
#print(aa)
|
|
206
|
+
#aac = generate_matrix_element_ſ(0, 1, np.array([1,0,0]), np.array([0,0,1]), C_const, np.array([1.0,1.0,1.0]))
|
|
207
|
+
#print(aac/8)
|
|
208
|
+
#print(gamma_matrix(1, C_const, np.array([1.0, 1.0, 1.0])))
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
#include <Python.h>
|
|
5
|
+
#include <numpy/arrayobject.h>
|
|
6
|
+
#include <math.h>
|
|
7
|
+
#include <omp.h>
|
|
8
|
+
|
|
9
|
+
double fact2(int N)
|
|
10
|
+
{
|
|
11
|
+
if (N < -1)
|
|
12
|
+
{
|
|
13
|
+
printf("Arithmetic Error: Cannot get double factorial of an input less than -1\n");
|
|
14
|
+
exit(EXIT_FAILURE);
|
|
15
|
+
} else if ( N == 0 || N == -1 || N == 1){
|
|
16
|
+
return 1.0;
|
|
17
|
+
} else {
|
|
18
|
+
double prod = 1.0;
|
|
19
|
+
for (int i = N; i > 1; i-=2)
|
|
20
|
+
{
|
|
21
|
+
prod = prod * i;
|
|
22
|
+
//printf("i: %i, prod: %li\n", i, prod);
|
|
23
|
+
}
|
|
24
|
+
return prod;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
int it_c(int i, int j)
|
|
29
|
+
{
|
|
30
|
+
int index;
|
|
31
|
+
if (i == j) { index = i;}
|
|
32
|
+
else {index = 6 - (i +j);}
|
|
33
|
+
return index;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
double generate_term_in_gamma_matrix_element(int exp_index1[3], int exp_index2[3], int i1, int i2, int j1, int j2, double C[6][6], double geo_par[3], int options)
|
|
37
|
+
{
|
|
38
|
+
int coeff[3], Q, S;
|
|
39
|
+
int array_j1[3] = {0,0,0};
|
|
40
|
+
int array_j2[3] = {0,0,0};
|
|
41
|
+
double R, alpha, beta, P;
|
|
42
|
+
array_j1[j1] = 1;
|
|
43
|
+
array_j2[j2] = 1;
|
|
44
|
+
for (int i = 0; i < 3; i++) {coeff[i] = exp_index1[i] + exp_index2[i] + 1 - array_j1[i] - array_j2[i];}
|
|
45
|
+
Q = (1 - (int)pow(-1,coeff[0]))*(1 - (int)pow(-1,coeff[1]))*(1 - (int)pow(-1,coeff[2]));
|
|
46
|
+
S = exp_index1[j1]*exp_index2[j2];
|
|
47
|
+
if (Q == 0 || S == 0)
|
|
48
|
+
{
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
if (options == 1)
|
|
52
|
+
{
|
|
53
|
+
R = (0.0+fact2(coeff[0] - 2)*fact2(coeff[1] - 2))/(fact2(coeff[0] + coeff[1])*coeff[2]);
|
|
54
|
+
alpha = M_PI/4;
|
|
55
|
+
} else if (options == 2) {
|
|
56
|
+
R = (0.0+fact2(coeff[0] - 2)*fact2(coeff[1] - 2)*fact2(coeff[2] - 2))/fact2(coeff[0] + coeff[1] + coeff[2]);
|
|
57
|
+
alpha = M_PI/6;
|
|
58
|
+
} else {
|
|
59
|
+
R = 1.0/(coeff[0]*coeff[1]*coeff[2]);
|
|
60
|
+
alpha = 1.0;
|
|
61
|
+
}
|
|
62
|
+
if (j1 == j2) {beta = (geo_par[0]*geo_par[1]*geo_par[2])/pow(geo_par[j1],2);}
|
|
63
|
+
else {beta = geo_par[3-j1-j2];}
|
|
64
|
+
P = 4*alpha*C[it_c(i1,j1)][it_c(i2,j2)]*beta;
|
|
65
|
+
//for (int i = 0; i < 6; i++){ for (int j = 0; j < 6; j++) {printf("%f ", C[i][j]);} printf("\n");}
|
|
66
|
+
//for (int i = 0; i < 3; i++) {printf("%f, %i, %i\n", geo_par[i], exp_index1[i], exp_index2[i]); }
|
|
67
|
+
return P*Q*S*R;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
double generate_gamma_matrix_element(int i1, int i2, int exp_index1[3], int exp_index2[3], double C[6][6], double geo_par[3], int options)
|
|
71
|
+
{
|
|
72
|
+
double suma = 0.0;
|
|
73
|
+
for (int j = 0; j < 3; j++)
|
|
74
|
+
{
|
|
75
|
+
for (int l = 0; l < 3; l++)
|
|
76
|
+
{
|
|
77
|
+
suma += generate_term_in_gamma_matrix_element(exp_index1, exp_index2, i1, i2, j, l, C, geo_par, options);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return suma;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
double generate_E_matrix_element(int i1, int i2, int exp_index1[3], int exp_index2[3], int options)
|
|
84
|
+
{
|
|
85
|
+
if (i1 != i2)
|
|
86
|
+
{
|
|
87
|
+
return 0.0;
|
|
88
|
+
} else {
|
|
89
|
+
int coeff[3], Q;
|
|
90
|
+
double R;
|
|
91
|
+
for (int i = 0; i < 3; i++) {coeff[i] = exp_index1[i] + exp_index2[i] + 1;}
|
|
92
|
+
Q = (1 - (int)pow(-1,coeff[0]))*(1 - (int)pow(-1,coeff[1]))*(1 - (int)pow(-1,coeff[2]));
|
|
93
|
+
if (Q == 0)
|
|
94
|
+
{
|
|
95
|
+
return 0.0;
|
|
96
|
+
}
|
|
97
|
+
if (options == 1)
|
|
98
|
+
{
|
|
99
|
+
R = (0.0+fact2(coeff[0] - 2)*fact2(coeff[1] - 2))/(fact2(coeff[0] + coeff[1])*coeff[2]);
|
|
100
|
+
} else if (options == 2) {
|
|
101
|
+
R = (0.0+fact2(coeff[0] - 2)*fact2(coeff[1] - 2)*fact2(coeff[2] - 2))/(0.0+fact2(coeff[0] + coeff[1] + coeff[2]));
|
|
102
|
+
} else {
|
|
103
|
+
R = 1.0/(coeff[0]*coeff[1]*coeff[2]);
|
|
104
|
+
}
|
|
105
|
+
//for (int i = 0; i < 3; i++) {printf("coeff %i: %i, fact: %li \n", i, coeff[i], fact2(coeff[i]));}
|
|
106
|
+
//printf("Operacion 1: %li\n", (fact2(coeff[0] - 2)*fact2(coeff[1] - 2)));
|
|
107
|
+
//printf("Operacion 2: %li\n", fact2(coeff[0] + coeff[1])*coeff[2]);
|
|
108
|
+
//printf("35!!= %f\n", fact2(35));
|
|
109
|
+
return Q*R;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Function to generate combinations
|
|
114
|
+
int **generate_combinations(int N) {
|
|
115
|
+
int R = ((N + 1) * (N + 2) * (N + 3))/6;
|
|
116
|
+
|
|
117
|
+
// Allocate memory for the combinations array
|
|
118
|
+
int **combi = (int **)malloc(R * sizeof(int *));
|
|
119
|
+
for (int i = 0; i < R; i++)
|
|
120
|
+
{
|
|
121
|
+
combi[i] = (int *)malloc(3 * sizeof(int));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
int l = 0;
|
|
125
|
+
for (int n = 0; n <= N; n++) {
|
|
126
|
+
for (int i = 0; i <= n; i++) {
|
|
127
|
+
for (int j = 0; j <= n - i; j++) {
|
|
128
|
+
int k = n - i - j;
|
|
129
|
+
combi[l][0] = i;
|
|
130
|
+
combi[l][1] = j;
|
|
131
|
+
combi[l][2] = k;
|
|
132
|
+
l++;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return combi;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
// Function to free allocated memory
|
|
141
|
+
void free_combinations(int **combi, int total_combinations) {
|
|
142
|
+
for (int i = 0; i < total_combinations; i++) {
|
|
143
|
+
free(combi[i]);
|
|
144
|
+
}
|
|
145
|
+
free(combi);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
PyObject *gamma_matrix_py(PyObject *self, PyObject *args)
|
|
149
|
+
{
|
|
150
|
+
PyArrayObject *C, *geo_par;
|
|
151
|
+
int N, options;
|
|
152
|
+
|
|
153
|
+
if (!PyArg_ParseTuple(args, "iO!O!i", &N, &PyArray_Type, &C, &PyArray_Type, &geo_par, &options))
|
|
154
|
+
{
|
|
155
|
+
return NULL;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!PyArray_Check(C) || !PyArray_Check(geo_par))
|
|
159
|
+
{
|
|
160
|
+
PyErr_SetString(PyExc_TypeError, "Expected numpy arrays for C and geo_par");
|
|
161
|
+
return NULL;
|
|
162
|
+
}
|
|
163
|
+
double *geo_par_data = (double *)PyArray_DATA(geo_par);
|
|
164
|
+
double (*C_data)[6] = (double (*)[6])PyArray_DATA(C);
|
|
165
|
+
|
|
166
|
+
if (PyArray_NDIM(geo_par) != 1 || PyArray_DIM(geo_par, 0) != 3 ||
|
|
167
|
+
PyArray_NDIM(C) != 2 || PyArray_DIM(C, 0) != 6 || PyArray_DIM(C, 1) != 6)
|
|
168
|
+
{
|
|
169
|
+
PyErr_SetString(PyExc_ValueError, "C must be an np.array of dimensions (6,6) and geo_par must be an array of dimensions (3,)");
|
|
170
|
+
return NULL;
|
|
171
|
+
}
|
|
172
|
+
/*
|
|
173
|
+
* Aquí se empieza a escribir la función de verdad. Bueno casi. Aquí definimos que tan grande queremos que sea la matriz de respuesta
|
|
174
|
+
*/
|
|
175
|
+
int R = ((N + 1)*(N + 2)*(N + 3))/6;
|
|
176
|
+
npy_intp dims[2] = {3*R, 3*R};
|
|
177
|
+
PyObject *gamma_array = PyArray_SimpleNew(2, dims, NPY_DOUBLE);
|
|
178
|
+
if (gamma_array == NULL)
|
|
179
|
+
{
|
|
180
|
+
PyErr_SetString(PyExc_MemoryError, "Gamma array memory could be not allocated");
|
|
181
|
+
return NULL;
|
|
182
|
+
}
|
|
183
|
+
double *gamma_data = (double *)PyArray_DATA((PyArrayObject *)gamma_array);
|
|
184
|
+
/*
|
|
185
|
+
* Ahora sí aquí empiezas a codificar la lógica de la función
|
|
186
|
+
*/
|
|
187
|
+
int **combi;
|
|
188
|
+
combi = generate_combinations(N); //Recuerde que el primer índice de combi es la combinación específica y el segundo va de cero a 2
|
|
189
|
+
if (combi == NULL)
|
|
190
|
+
{
|
|
191
|
+
PyErr_SetString(PyExc_MemoryError, "Combinations array memory could not be allocated");
|
|
192
|
+
Py_DECREF(gamma_array); // Free gamma_array if combi allocation fails
|
|
193
|
+
return NULL;
|
|
194
|
+
}
|
|
195
|
+
#pragma omp parallel for collapse(4)
|
|
196
|
+
for (int i = 0; i < 3; i++)
|
|
197
|
+
{
|
|
198
|
+
for (int k = 0; k < 3; k++)
|
|
199
|
+
{
|
|
200
|
+
for (int lm = 0; lm < R; lm++)
|
|
201
|
+
{
|
|
202
|
+
for (int lf = 0; lf < R; lf++)
|
|
203
|
+
{
|
|
204
|
+
gamma_data[3*R*(i*R +lm) + (k*R + lf)] = generate_gamma_matrix_element(i, k, combi[lm], combi[lf], C_data, geo_par_data, options);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
free_combinations(combi, R);
|
|
210
|
+
//printf("Hello from C \n");
|
|
211
|
+
return gamma_array;
|
|
212
|
+
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
PyObject *E_matrix_py(PyObject *self, PyObject *args)
|
|
216
|
+
{
|
|
217
|
+
int N, options;
|
|
218
|
+
if (!PyArg_ParseTuple(args, "ii", &N, &options))
|
|
219
|
+
{
|
|
220
|
+
return NULL;
|
|
221
|
+
}
|
|
222
|
+
int R = ((N + 1)*(N + 2)*(N + 3))/6;
|
|
223
|
+
int **combi;
|
|
224
|
+
npy_intp dims[2] = {3*R, 3*R};
|
|
225
|
+
PyObject *E_array = PyArray_SimpleNew(2, dims, NPY_DOUBLE);
|
|
226
|
+
if (E_array == NULL)
|
|
227
|
+
{
|
|
228
|
+
PyErr_SetString(PyExc_MemoryError, "Memory for E matrix could not be allocated");
|
|
229
|
+
return NULL;
|
|
230
|
+
}
|
|
231
|
+
double *E_data = (double *)PyArray_DATA((PyArrayObject *)E_array);
|
|
232
|
+
combi = generate_combinations(N);
|
|
233
|
+
|
|
234
|
+
if (combi == NULL) {
|
|
235
|
+
PyErr_SetString(PyExc_MemoryError, "Combinations array memory could not be allocated");
|
|
236
|
+
Py_DECREF(E_array);
|
|
237
|
+
return NULL;
|
|
238
|
+
}
|
|
239
|
+
#pragma omp parallel for collapse(4)
|
|
240
|
+
for (int i = 0; i < 3; i++)
|
|
241
|
+
{
|
|
242
|
+
for (int k = 0; k < 3; k++)
|
|
243
|
+
{
|
|
244
|
+
for (int lm = 0; lm < R; lm++)
|
|
245
|
+
{
|
|
246
|
+
for (int lf = 0; lf < R; lf++)
|
|
247
|
+
{
|
|
248
|
+
E_data[3*R*(i*R +lm) + (k*R + lf)] = generate_E_matrix_element(i, k, combi[lm], combi[lf], options);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
free_combinations(combi, R);
|
|
254
|
+
return E_array;
|
|
255
|
+
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
PyObject *generate_element_in_gamma_matrix_py(PyObject *self, PyObject *args)
|
|
259
|
+
{
|
|
260
|
+
PyArrayObject *exp_index1, *exp_index2, *C, *geo_par;
|
|
261
|
+
int i1, i2, options;
|
|
262
|
+
double result;
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
if (!PyArg_ParseTuple(args, "iiO!O!O!O!i",
|
|
266
|
+
&i1, &i2,
|
|
267
|
+
&PyArray_Type, &exp_index1,
|
|
268
|
+
&PyArray_Type, &exp_index2,
|
|
269
|
+
&PyArray_Type, &C,
|
|
270
|
+
&PyArray_Type, &geo_par,
|
|
271
|
+
&options))
|
|
272
|
+
{
|
|
273
|
+
return NULL;
|
|
274
|
+
}
|
|
275
|
+
// Validate input arrays
|
|
276
|
+
if (!PyArray_Check(exp_index1) || !PyArray_Check(exp_index2) ||
|
|
277
|
+
!PyArray_Check(C) || !PyArray_Check(geo_par))
|
|
278
|
+
{
|
|
279
|
+
PyErr_SetString(PyExc_TypeError, "Expected numpy arrays for exp_index1, exp_index2, C, and geo_par.");
|
|
280
|
+
return NULL;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Convert numpy arrays to C arrays
|
|
284
|
+
int *exp_index1_data = (int *)PyArray_DATA(exp_index1);
|
|
285
|
+
int *exp_index2_data = (int *)PyArray_DATA(exp_index2);
|
|
286
|
+
double (*C_data)[6] = (double (*)[6])PyArray_DATA(C);
|
|
287
|
+
double *geo_par_data = (double *)PyArray_DATA(geo_par);
|
|
288
|
+
|
|
289
|
+
// Ensure dimensions match expected sizes
|
|
290
|
+
if (PyArray_NDIM(exp_index1) != 1 || PyArray_DIM(exp_index1, 0) != 3 ||
|
|
291
|
+
PyArray_NDIM(exp_index2) != 1 || PyArray_DIM(exp_index2, 0) != 3 ||
|
|
292
|
+
PyArray_NDIM(C) != 2 || PyArray_DIM(C, 0) != 6 || PyArray_DIM(C, 1) != 6 ||
|
|
293
|
+
PyArray_NDIM(geo_par) != 1 || PyArray_DIM(geo_par, 0) != 3)
|
|
294
|
+
{
|
|
295
|
+
PyErr_SetString(PyExc_ValueError, "Invalid dimensions for input arrays.");
|
|
296
|
+
return NULL;
|
|
297
|
+
}
|
|
298
|
+
//for (int i = 0; i < 3; i++) {printf("|%i|%i|\n", exp_index1_data[i], exp_index2_data[i]);}
|
|
299
|
+
// Call the C function
|
|
300
|
+
result = generate_gamma_matrix_element(i1, i2, exp_index1_data, exp_index2_data,
|
|
301
|
+
C_data,
|
|
302
|
+
geo_par_data, options);
|
|
303
|
+
|
|
304
|
+
// Return the result as a Python float
|
|
305
|
+
return PyFloat_FromDouble(result);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
PyObject *generate_element_in_E_matrix_py(PyObject *self, PyObject *args)
|
|
309
|
+
{
|
|
310
|
+
PyArrayObject *exp_index1, *exp_index2;
|
|
311
|
+
int i1, i2, options;
|
|
312
|
+
double result;
|
|
313
|
+
if (!PyArg_ParseTuple(args, "iiO!O!i",
|
|
314
|
+
&i1, &i2,
|
|
315
|
+
&PyArray_Type, &exp_index1,
|
|
316
|
+
&PyArray_Type, &exp_index2,
|
|
317
|
+
&options))
|
|
318
|
+
{
|
|
319
|
+
return NULL;
|
|
320
|
+
}
|
|
321
|
+
if (!PyArray_Check(exp_index1) || !PyArray_Check(exp_index2))
|
|
322
|
+
{
|
|
323
|
+
PyErr_SetString(PyExc_TypeError, "Expected numpy arrays for exp_index1 and exp_index2");
|
|
324
|
+
return NULL;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
int *exp_index1_data = (int *)PyArray_DATA(exp_index1);
|
|
328
|
+
int *exp_index2_data = (int *)PyArray_DATA(exp_index2);
|
|
329
|
+
if (PyArray_NDIM(exp_index1) != 1 || PyArray_DIM(exp_index1, 0) != 3 ||
|
|
330
|
+
PyArray_NDIM(exp_index2) != 1 || PyArray_DIM(exp_index2, 0) != 3)
|
|
331
|
+
{
|
|
332
|
+
PyErr_SetString(PyExc_ValueError, "Invalid dimensions for exp_index1 or exp_index2. Must be (3,)");
|
|
333
|
+
return NULL;
|
|
334
|
+
}
|
|
335
|
+
result = generate_E_matrix_element(i1, i2, exp_index1_data, exp_index2_data, options);
|
|
336
|
+
return PyFloat_FromDouble(result);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
static PyMethodDef methods[] = {
|
|
341
|
+
{"generate_gamma_matrix_element", generate_element_in_gamma_matrix_py, METH_VARARGS, "This functions generates a term in teh sum of an element of gamma matrix"},
|
|
342
|
+
{"generate_E_matrix_element", generate_element_in_E_matrix_py, METH_VARARGS, "This function generates a matrix element of E"},
|
|
343
|
+
{"gamma_matrix", gamma_matrix_py, METH_VARARGS, "This function computes the gamma matrix"},
|
|
344
|
+
{"E_matrix", E_matrix_py, METH_VARARGS, "This function computes the E matrix"},
|
|
345
|
+
{NULL, NULL, 0, NULL}
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
static struct PyModuleDef rus_module = {
|
|
349
|
+
PyModuleDef_HEAD_INIT,
|
|
350
|
+
"rus",
|
|
351
|
+
"Prototipo de modelo de rus.",
|
|
352
|
+
-1,
|
|
353
|
+
methods
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
PyMODINIT_FUNC PyInit_rus()
|
|
357
|
+
{
|
|
358
|
+
PyObject *module = PyModule_Create(&rus_module);
|
|
359
|
+
import_array();
|
|
360
|
+
return module;
|
|
361
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ruspectroscopy-tools
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A simple tool that generates Gamma matrix and E matrix, given the elastic constants, mass, dimansions and shape of a sample, in Resonant Ultrasound Spectroscopy. Use scipy.linalg.eigh(...) to solve the forward problem
|
|
5
|
+
Home-page: https://github.com/jacubillos10/RUSpectroscopy_Tools
|
|
6
|
+
Author: Alejandro Cubillos
|
|
7
|
+
Author-email: alejandro4cm@outlook.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
|
|
16
|
+
# RUSpectroscopy_tools
|
|
17
|
+
|
|
18
|
+
A C extension module for generating Gamma and Epsilon matrices, in Resonant Ultrasound Spectroscopy.
|
|
19
|
+
|
|
20
|
+
## Authors
|
|
21
|
+
|
|
22
|
+
- Alejandro Cubillos - alejandro4cm@outlook.com
|
|
23
|
+
- Manuela Rivas
|
|
24
|
+
- Julián Rincón
|
|
25
|
+
|
|
26
|
+
## Import:
|
|
27
|
+
```python
|
|
28
|
+
from rusmodules import rus
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage Example
|
|
32
|
+
```python
|
|
33
|
+
gamma = rus.gamma_matrix(N, C, geometry, shape)
|
|
34
|
+
E = rus.E_matrix(N, shape)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
# Where:
|
|
38
|
+
* N <int> represents the maximim grade of the polynomials of the basis functions
|
|
39
|
+
* C <np.array> 6x6 matrix with the elastic constants
|
|
40
|
+
* geometry <np.array> (3,) shape array containing the dimensions of the sample
|
|
41
|
+
* shape <int> 0 for parallelepiped, 1 for cylinder and 2 to spheroid
|
|
42
|
+
|
|
43
|
+
Solve forward problem with scipy:
|
|
44
|
+
Eigenvalues return $m\omega^2$
|
|
45
|
+
```python
|
|
46
|
+
eigenvals, eigenvects = scipy.linalg.eigh(a = gamma, b = E)
|
|
47
|
+
omega = (eigenvals[6:]/m)**(1/2) #remember the fisrt 6 eigenvalues must be near zero
|
|
48
|
+
frequencies = omega/(2*np.pi)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Installation:
|
|
52
|
+
```bash
|
|
53
|
+
pip3 install ruspectroscopy_tools
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
rusmodules/__init__.py
|
|
6
|
+
rusmodules/compile_data_generator.py
|
|
7
|
+
rusmodules/compile_rus_module.py
|
|
8
|
+
rusmodules/rus.c
|
|
9
|
+
ruspectroscopy_tools.egg-info/PKG-INFO
|
|
10
|
+
ruspectroscopy_tools.egg-info/SOURCES.txt
|
|
11
|
+
ruspectroscopy_tools.egg-info/dependency_links.txt
|
|
12
|
+
ruspectroscopy_tools.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rusmodules
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from setuptools import setup, Extension
|
|
2
|
+
import numpy as np
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
extra_compile_flags = ["-fopenmp"]
|
|
6
|
+
extra_link_flags = ["-fopenmp"]
|
|
7
|
+
|
|
8
|
+
setup(
|
|
9
|
+
name = "ruspectroscopy_tools",
|
|
10
|
+
version = "0.0.1",
|
|
11
|
+
description = "A simple tool that generates Gamma matrix and E matrix, given the elastic constants, mass, dimansions and shape of a sample, in Resonant Ultrasound Spectroscopy. Use scipy.linalg.eigh(...) to solve the forward problem",
|
|
12
|
+
long_description = open("README.md").read(),
|
|
13
|
+
long_description_content_type = "text/markdown",
|
|
14
|
+
author = "Alejandro Cubillos",
|
|
15
|
+
author_email = "alejandro4cm@outlook.com",
|
|
16
|
+
url = "https://github.com/jacubillos10/RUSpectroscopy_Tools",
|
|
17
|
+
packages = ["rusmodules"],
|
|
18
|
+
ext_modules = [
|
|
19
|
+
Extension(
|
|
20
|
+
"rusmodules.rus",
|
|
21
|
+
sources = ["rusmodules/rus.c"],
|
|
22
|
+
include_dirs = [np.get_include()],
|
|
23
|
+
extra_compile_args = extra_compile_flags,
|
|
24
|
+
extra_link_args = extra_link_flags,
|
|
25
|
+
)
|
|
26
|
+
],
|
|
27
|
+
classifiers = [
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"License :: OSI Approved :: MIT License",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
],
|
|
32
|
+
license = "MIT",
|
|
33
|
+
python_requires = ">=3.6",
|
|
34
|
+
setup_requires = ["numpy"],
|
|
35
|
+
)
|