pylibsparseir 0.1.0__cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
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.
Potentially problematic release.
This version of pylibsparseir might be problematic. Click here for more details.
- pylibsparseir/clean_build_artifacts.py +72 -0
- pylibsparseir/constants.py +39 -0
- pylibsparseir/core.py +609 -0
- pylibsparseir/ctypes_wrapper.py +40 -0
- pylibsparseir/libsparseir.so +0 -0
- pylibsparseir/libsparseir.so.0 +0 -0
- pylibsparseir/libsparseir.so.0.4.2 +0 -0
- pylibsparseir-0.1.0.dist-info/METADATA +130 -0
- pylibsparseir-0.1.0.dist-info/RECORD +12 -0
- pylibsparseir-0.1.0.dist-info/WHEEL +6 -0
- pylibsparseir-0.1.0.dist-info/entry_points.txt +2 -0
- pylibsparseir-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Clean build artifacts and files copied by setup_build.py and included via MANIFEST.in
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import shutil
|
|
8
|
+
import glob
|
|
9
|
+
|
|
10
|
+
def clean_build_artifacts():
|
|
11
|
+
"""Remove build artifacts and copied files."""
|
|
12
|
+
current_dir = os.getcwd()
|
|
13
|
+
|
|
14
|
+
# Directories and files to remove (from setup_build.py and build artifacts)
|
|
15
|
+
items_to_remove = [
|
|
16
|
+
'build',
|
|
17
|
+
'dist',
|
|
18
|
+
'*.egg-info',
|
|
19
|
+
'include',
|
|
20
|
+
'src',
|
|
21
|
+
'fortran',
|
|
22
|
+
'cmake',
|
|
23
|
+
'CMakeLists.txt'
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
# Files in pylibsparseir to remove
|
|
27
|
+
pylibsparseir_patterns = [
|
|
28
|
+
'pylibsparseir/*.so',
|
|
29
|
+
'pylibsparseir/*.dylib',
|
|
30
|
+
'pylibsparseir/*.dll',
|
|
31
|
+
'pylibsparseir/__pycache__'
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
print(f"Cleaning build artifacts in: {current_dir}")
|
|
35
|
+
|
|
36
|
+
# Remove main items
|
|
37
|
+
for item in items_to_remove:
|
|
38
|
+
if '*' in item:
|
|
39
|
+
# Handle glob patterns
|
|
40
|
+
for path in glob.glob(item):
|
|
41
|
+
if os.path.exists(path):
|
|
42
|
+
if os.path.isdir(path):
|
|
43
|
+
shutil.rmtree(path)
|
|
44
|
+
print(f"Removed directory: {path}")
|
|
45
|
+
else:
|
|
46
|
+
os.remove(path)
|
|
47
|
+
print(f"Removed file: {path}")
|
|
48
|
+
else:
|
|
49
|
+
# Handle direct paths
|
|
50
|
+
if os.path.exists(item):
|
|
51
|
+
if os.path.isdir(item):
|
|
52
|
+
shutil.rmtree(item)
|
|
53
|
+
print(f"Removed directory: {item}")
|
|
54
|
+
else:
|
|
55
|
+
os.remove(item)
|
|
56
|
+
print(f"Removed file: {item}")
|
|
57
|
+
|
|
58
|
+
# Remove pylibsparseir artifacts
|
|
59
|
+
for pattern in pylibsparseir_patterns:
|
|
60
|
+
for path in glob.glob(pattern):
|
|
61
|
+
if os.path.exists(path):
|
|
62
|
+
if os.path.isdir(path):
|
|
63
|
+
shutil.rmtree(path)
|
|
64
|
+
print(f"Removed directory: {path}")
|
|
65
|
+
else:
|
|
66
|
+
os.remove(path)
|
|
67
|
+
print(f"Removed file: {path}")
|
|
68
|
+
|
|
69
|
+
print("Clean completed!")
|
|
70
|
+
|
|
71
|
+
if __name__ == "__main__":
|
|
72
|
+
clean_build_artifacts()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Constants used in the SparseIR C API.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# Status codes
|
|
6
|
+
COMPUTATION_SUCCESS = 0
|
|
7
|
+
GET_IMPL_FAILED = -1
|
|
8
|
+
INVALID_DIMENSION = -2
|
|
9
|
+
INPUT_DIMENSION_MISMATCH = -3
|
|
10
|
+
OUTPUT_DIMENSION_MISMATCH = -4
|
|
11
|
+
NOT_SUPPORTED = -5
|
|
12
|
+
INVALID_ARGUMENT = -6
|
|
13
|
+
INTERNAL_ERROR = -7
|
|
14
|
+
|
|
15
|
+
# SPIR prefixed constants for compatibility
|
|
16
|
+
SPIR_COMPUTATION_SUCCESS = 0
|
|
17
|
+
SPIR_GET_IMPL_FAILED = -1
|
|
18
|
+
SPIR_INVALID_DIMENSION = -2
|
|
19
|
+
SPIR_INPUT_DIMENSION_MISMATCH = -3
|
|
20
|
+
SPIR_OUTPUT_DIMENSION_MISMATCH = -4
|
|
21
|
+
SPIR_NOT_SUPPORTED = -5
|
|
22
|
+
SPIR_INVALID_ARGUMENT = -6
|
|
23
|
+
SPIR_INTERNAL_ERROR = -7
|
|
24
|
+
|
|
25
|
+
# Statistics type constants
|
|
26
|
+
SPIR_STATISTICS_FERMIONIC = 1
|
|
27
|
+
SPIR_STATISTICS_BOSONIC = 0
|
|
28
|
+
|
|
29
|
+
# Order type constants
|
|
30
|
+
SPIR_ORDER_COLUMN_MAJOR = 1
|
|
31
|
+
SPIR_ORDER_ROW_MAJOR = 0
|
|
32
|
+
|
|
33
|
+
# Make sure these are available at module level
|
|
34
|
+
SPIR_ORDER_ROW_MAJOR = 0
|
|
35
|
+
SPIR_ORDER_COLUMN_MAJOR = 1
|
|
36
|
+
|
|
37
|
+
# SVE Twork constants
|
|
38
|
+
SPIR_TWORK_FLOAT64 = 0
|
|
39
|
+
SPIR_TWORK_FLOAT64X2 = 1
|
pylibsparseir/core.py
ADDED
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core functionality for the SparseIR Python bindings.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
import ctypes
|
|
8
|
+
from ctypes import c_int, c_double, c_int64, c_size_t, c_bool, POINTER, byref
|
|
9
|
+
from ctypes import CDLL
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
from .ctypes_wrapper import spir_kernel, spir_sve_result, spir_basis, spir_funcs, spir_sampling
|
|
13
|
+
from pylibsparseir.constants import COMPUTATION_SUCCESS, SPIR_ORDER_ROW_MAJOR, SPIR_ORDER_COLUMN_MAJOR, SPIR_TWORK_FLOAT64, SPIR_TWORK_FLOAT64X2, SPIR_STATISTICS_FERMIONIC, SPIR_STATISTICS_BOSONIC
|
|
14
|
+
|
|
15
|
+
def _find_library():
|
|
16
|
+
"""Find the SparseIR shared library."""
|
|
17
|
+
if sys.platform == "darwin":
|
|
18
|
+
libname = "libsparseir.dylib"
|
|
19
|
+
elif sys.platform == "win32":
|
|
20
|
+
libname = "sparseir.dll"
|
|
21
|
+
else:
|
|
22
|
+
libname = "libsparseir.so"
|
|
23
|
+
|
|
24
|
+
# Try to find the library in common locations
|
|
25
|
+
search_paths = [
|
|
26
|
+
os.path.dirname(os.path.abspath(__file__)),
|
|
27
|
+
os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "build"),
|
|
28
|
+
os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "build"),
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
for path in search_paths:
|
|
32
|
+
libpath = os.path.join(path, libname)
|
|
33
|
+
if os.path.exists(libpath):
|
|
34
|
+
return libpath
|
|
35
|
+
|
|
36
|
+
raise RuntimeError(f"Could not find {libname} in {search_paths}")
|
|
37
|
+
|
|
38
|
+
# Load the library
|
|
39
|
+
try:
|
|
40
|
+
_lib = CDLL(_find_library())
|
|
41
|
+
except Exception as e:
|
|
42
|
+
raise RuntimeError(f"Failed to load SparseIR library: {e}")
|
|
43
|
+
|
|
44
|
+
class c_double_complex(ctypes.Structure):
|
|
45
|
+
"""complex is a c structure
|
|
46
|
+
https://docs.python.org/3/library/ctypes.html#module-ctypes suggests
|
|
47
|
+
to use ctypes.Structure to pass structures (and, therefore, complex)
|
|
48
|
+
See: https://stackoverflow.com/questions/13373291/complex-number-in-ctypes
|
|
49
|
+
"""
|
|
50
|
+
_fields_ = [("real", ctypes.c_double),("imag", ctypes.c_double)]
|
|
51
|
+
@property
|
|
52
|
+
def value(self):
|
|
53
|
+
return self.real+1j*self.imag # fields declared above
|
|
54
|
+
|
|
55
|
+
# Set up function prototypes
|
|
56
|
+
def _setup_prototypes():
|
|
57
|
+
# Kernel functions
|
|
58
|
+
_lib.spir_logistic_kernel_new.argtypes = [c_double, POINTER(c_int)]
|
|
59
|
+
_lib.spir_logistic_kernel_new.restype = spir_kernel
|
|
60
|
+
|
|
61
|
+
_lib.spir_reg_bose_kernel_new.argtypes = [c_double, POINTER(c_int)]
|
|
62
|
+
_lib.spir_reg_bose_kernel_new.restype = spir_kernel
|
|
63
|
+
|
|
64
|
+
_lib.spir_kernel_domain.argtypes = [
|
|
65
|
+
spir_kernel, POINTER(c_double), POINTER(c_double),
|
|
66
|
+
POINTER(c_double), POINTER(c_double)
|
|
67
|
+
]
|
|
68
|
+
_lib.spir_kernel_domain.restype = c_int
|
|
69
|
+
|
|
70
|
+
# SVE result functions
|
|
71
|
+
_lib.spir_sve_result_new.argtypes = [spir_kernel, c_double, c_double, c_int, c_int, c_int, POINTER(c_int)]
|
|
72
|
+
_lib.spir_sve_result_new.restype = spir_sve_result
|
|
73
|
+
|
|
74
|
+
_lib.spir_sve_result_get_size.argtypes = [spir_sve_result, POINTER(c_int)]
|
|
75
|
+
_lib.spir_sve_result_get_size.restype = c_int
|
|
76
|
+
|
|
77
|
+
_lib.spir_sve_result_get_svals.argtypes = [spir_sve_result, POINTER(c_double)]
|
|
78
|
+
_lib.spir_sve_result_get_svals.restype = c_int
|
|
79
|
+
|
|
80
|
+
# Basis functions
|
|
81
|
+
_lib.spir_basis_new.argtypes = [
|
|
82
|
+
c_int, c_double, c_double, spir_kernel, spir_sve_result, c_int, POINTER(c_int)
|
|
83
|
+
]
|
|
84
|
+
_lib.spir_basis_new.restype = spir_basis
|
|
85
|
+
|
|
86
|
+
_lib.spir_basis_get_size.argtypes = [spir_basis, POINTER(c_int)]
|
|
87
|
+
_lib.spir_basis_get_size.restype = c_int
|
|
88
|
+
|
|
89
|
+
_lib.spir_basis_get_svals.argtypes = [spir_basis, POINTER(c_double)]
|
|
90
|
+
_lib.spir_basis_get_svals.restype = c_int
|
|
91
|
+
|
|
92
|
+
_lib.spir_basis_get_stats.argtypes = [spir_basis, POINTER(c_int)]
|
|
93
|
+
_lib.spir_basis_get_stats.restype = c_int
|
|
94
|
+
|
|
95
|
+
# Basis function objects
|
|
96
|
+
_lib.spir_basis_get_u.argtypes = [spir_basis, POINTER(c_int)]
|
|
97
|
+
_lib.spir_basis_get_u.restype = spir_funcs
|
|
98
|
+
|
|
99
|
+
_lib.spir_basis_get_v.argtypes = [spir_basis, POINTER(c_int)]
|
|
100
|
+
_lib.spir_basis_get_v.restype = spir_funcs
|
|
101
|
+
|
|
102
|
+
_lib.spir_basis_get_uhat.argtypes = [spir_basis, POINTER(c_int)]
|
|
103
|
+
_lib.spir_basis_get_uhat.restype = spir_funcs
|
|
104
|
+
|
|
105
|
+
_lib.spir_funcs_get_slice.argtypes = [spir_funcs, c_int, POINTER(c_int), POINTER(c_int)]
|
|
106
|
+
_lib.spir_funcs_get_slice.restype = spir_funcs
|
|
107
|
+
|
|
108
|
+
# Function evaluation
|
|
109
|
+
_lib.spir_funcs_get_size.argtypes = [spir_funcs, POINTER(c_int)]
|
|
110
|
+
_lib.spir_funcs_get_size.restype = c_int
|
|
111
|
+
|
|
112
|
+
_lib.spir_funcs_eval.argtypes = [spir_funcs, c_double, POINTER(c_double)]
|
|
113
|
+
_lib.spir_funcs_eval.restype = c_int
|
|
114
|
+
|
|
115
|
+
_lib.spir_funcs_eval_matsu.argtypes = [spir_funcs, c_int64, POINTER(c_double_complex)]
|
|
116
|
+
_lib.spir_funcs_eval_matsu.restype = c_int
|
|
117
|
+
|
|
118
|
+
_lib.spir_funcs_batch_eval.argtypes = [
|
|
119
|
+
spir_funcs, c_int, c_size_t, POINTER(c_double), POINTER(c_double)
|
|
120
|
+
]
|
|
121
|
+
_lib.spir_funcs_batch_eval.restype = c_int
|
|
122
|
+
|
|
123
|
+
_lib.spir_funcs_batch_eval_matsu.argtypes = [
|
|
124
|
+
spir_funcs, c_int, c_int, POINTER(c_int64), POINTER(c_double)
|
|
125
|
+
]
|
|
126
|
+
_lib.spir_funcs_batch_eval_matsu.restype = c_int
|
|
127
|
+
|
|
128
|
+
_lib.spir_funcs_get_n_roots.argtypes = [spir_funcs, POINTER(c_int)]
|
|
129
|
+
_lib.spir_funcs_get_n_roots.restype = c_int
|
|
130
|
+
|
|
131
|
+
_lib.spir_funcs_get_roots.argtypes = [spir_funcs, POINTER(c_double)]
|
|
132
|
+
_lib.spir_funcs_get_roots.restype = c_int
|
|
133
|
+
|
|
134
|
+
# Default sampling points
|
|
135
|
+
_lib.spir_basis_get_n_default_taus.argtypes = [spir_basis, POINTER(c_int)]
|
|
136
|
+
_lib.spir_basis_get_n_default_taus.restype = c_int
|
|
137
|
+
|
|
138
|
+
_lib.spir_basis_get_default_taus.argtypes = [spir_basis, POINTER(c_double)]
|
|
139
|
+
_lib.spir_basis_get_default_taus.restype = c_int
|
|
140
|
+
|
|
141
|
+
_lib.spir_basis_get_default_taus_ext.argtypes = [spir_basis, c_int, POINTER(c_double), POINTER(c_int)]
|
|
142
|
+
_lib.spir_basis_get_default_taus_ext.restype = c_int
|
|
143
|
+
|
|
144
|
+
_lib.spir_basis_get_n_default_ws.argtypes = [spir_basis, POINTER(c_int)]
|
|
145
|
+
_lib.spir_basis_get_n_default_ws.restype = c_int
|
|
146
|
+
|
|
147
|
+
_lib.spir_basis_get_default_ws.argtypes = [spir_basis, POINTER(c_double)]
|
|
148
|
+
_lib.spir_basis_get_default_ws.restype = c_int
|
|
149
|
+
|
|
150
|
+
_lib.spir_basis_get_n_default_matsus.argtypes = [spir_basis, c_bool, POINTER(c_int)]
|
|
151
|
+
_lib.spir_basis_get_n_default_matsus.restype = c_int
|
|
152
|
+
|
|
153
|
+
_lib.spir_basis_get_n_default_matsus_ext.argtypes = [spir_basis, c_bool, c_int, POINTER(c_int)]
|
|
154
|
+
_lib.spir_basis_get_n_default_matsus_ext.restype = c_int
|
|
155
|
+
|
|
156
|
+
_lib.spir_basis_get_default_matsus.argtypes = [spir_basis, c_bool, POINTER(c_int64)]
|
|
157
|
+
_lib.spir_basis_get_default_matsus.restype = c_int
|
|
158
|
+
|
|
159
|
+
_lib.spir_basis_get_default_matsus_ext.argtypes = [spir_basis, c_bool, c_int, POINTER(c_int64), POINTER(c_int)]
|
|
160
|
+
_lib.spir_basis_get_default_matsus_ext.restype = c_int
|
|
161
|
+
|
|
162
|
+
# Sampling objects
|
|
163
|
+
_lib.spir_tau_sampling_new.argtypes = [spir_basis, c_int, POINTER(c_double), POINTER(c_int)]
|
|
164
|
+
_lib.spir_tau_sampling_new.restype = spir_sampling
|
|
165
|
+
|
|
166
|
+
_lib.spir_tau_sampling_new_with_matrix.argtypes = [c_int, c_int, c_int, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_int)]
|
|
167
|
+
_lib.spir_tau_sampling_new_with_matrix.restype = spir_sampling
|
|
168
|
+
|
|
169
|
+
_lib.spir_matsu_sampling_new.argtypes = [spir_basis, c_bool, c_int, POINTER(c_int64), POINTER(c_int)]
|
|
170
|
+
_lib.spir_matsu_sampling_new.restype = spir_sampling
|
|
171
|
+
|
|
172
|
+
_lib.spir_matsu_sampling_new_with_matrix.argtypes = [
|
|
173
|
+
c_int, # order
|
|
174
|
+
c_int, # statistics
|
|
175
|
+
c_int, # basis_size
|
|
176
|
+
c_bool, # positive_only
|
|
177
|
+
c_int, # num_points
|
|
178
|
+
POINTER(c_int64), # points
|
|
179
|
+
POINTER(c_double_complex), # matrix
|
|
180
|
+
POINTER(c_int) # status
|
|
181
|
+
]
|
|
182
|
+
_lib.spir_matsu_sampling_new_with_matrix.restype = spir_sampling
|
|
183
|
+
|
|
184
|
+
# Sampling operations
|
|
185
|
+
_lib.spir_sampling_eval_dd.argtypes = [
|
|
186
|
+
spir_sampling, c_int, c_int, POINTER(c_int), c_int,
|
|
187
|
+
POINTER(c_double), POINTER(c_double)
|
|
188
|
+
]
|
|
189
|
+
_lib.spir_sampling_eval_dd.restype = c_int
|
|
190
|
+
|
|
191
|
+
_lib.spir_sampling_fit_dd.argtypes = [
|
|
192
|
+
spir_sampling, c_int, c_int, POINTER(c_int), c_int,
|
|
193
|
+
POINTER(c_double), POINTER(c_double)
|
|
194
|
+
]
|
|
195
|
+
_lib.spir_sampling_fit_dd.restype = c_int
|
|
196
|
+
|
|
197
|
+
# Additional sampling functions
|
|
198
|
+
_lib.spir_sampling_get_npoints.argtypes = [spir_sampling, POINTER(c_int)]
|
|
199
|
+
_lib.spir_sampling_get_npoints.restype = c_int
|
|
200
|
+
|
|
201
|
+
_lib.spir_sampling_get_taus.argtypes = [spir_sampling, POINTER(c_double)]
|
|
202
|
+
_lib.spir_sampling_get_taus.restype = c_int
|
|
203
|
+
|
|
204
|
+
_lib.spir_sampling_get_matsus.argtypes = [spir_sampling, POINTER(c_int64)]
|
|
205
|
+
_lib.spir_sampling_get_matsus.restype = c_int
|
|
206
|
+
|
|
207
|
+
_lib.spir_sampling_get_cond_num.argtypes = [spir_sampling, POINTER(c_double)]
|
|
208
|
+
_lib.spir_sampling_get_cond_num.restype = c_int
|
|
209
|
+
|
|
210
|
+
# Multi-dimensional sampling evaluation functions
|
|
211
|
+
_lib.spir_sampling_eval_dz.argtypes = [
|
|
212
|
+
spir_sampling, c_int, c_int, POINTER(c_int), c_int,
|
|
213
|
+
POINTER(c_double), POINTER(c_double_complex)
|
|
214
|
+
]
|
|
215
|
+
_lib.spir_sampling_eval_dz.restype = c_int
|
|
216
|
+
|
|
217
|
+
_lib.spir_sampling_eval_zz.argtypes = [
|
|
218
|
+
spir_sampling, c_int, c_int, POINTER(c_int), c_int,
|
|
219
|
+
POINTER(c_double_complex), POINTER(c_double_complex)
|
|
220
|
+
]
|
|
221
|
+
_lib.spir_sampling_eval_zz.restype = c_int
|
|
222
|
+
|
|
223
|
+
_lib.spir_sampling_fit_zz.argtypes = [
|
|
224
|
+
spir_sampling, c_int, c_int, POINTER(c_int), c_int,
|
|
225
|
+
POINTER(c_double_complex), POINTER(c_double_complex)
|
|
226
|
+
]
|
|
227
|
+
_lib.spir_sampling_fit_zz.restype = c_int
|
|
228
|
+
|
|
229
|
+
# DLR functions
|
|
230
|
+
_lib.spir_dlr_new.argtypes = [spir_basis, POINTER(c_int)]
|
|
231
|
+
_lib.spir_dlr_new.restype = spir_basis
|
|
232
|
+
|
|
233
|
+
_lib.spir_dlr_new_with_poles.argtypes = [spir_basis, c_int, POINTER(c_double), POINTER(c_int)]
|
|
234
|
+
_lib.spir_dlr_new_with_poles.restype = spir_basis
|
|
235
|
+
|
|
236
|
+
_lib.spir_dlr_get_npoles.argtypes = [spir_basis, POINTER(c_int)]
|
|
237
|
+
_lib.spir_dlr_get_npoles.restype = c_int
|
|
238
|
+
|
|
239
|
+
_lib.spir_dlr_get_poles.argtypes = [spir_basis, POINTER(c_double)]
|
|
240
|
+
_lib.spir_dlr_get_poles.restype = c_int
|
|
241
|
+
|
|
242
|
+
_lib.spir_dlr2ir_dd.argtypes = [
|
|
243
|
+
spir_basis, c_int, c_int, POINTER(c_int), c_int,
|
|
244
|
+
POINTER(c_double), POINTER(c_double)
|
|
245
|
+
]
|
|
246
|
+
_lib.spir_dlr2ir_dd.restype = c_int
|
|
247
|
+
|
|
248
|
+
_lib.spir_dlr2ir_zz.argtypes = [
|
|
249
|
+
spir_basis, c_int, c_int, POINTER(c_int), c_int,
|
|
250
|
+
POINTER(c_double), POINTER(c_double)
|
|
251
|
+
]
|
|
252
|
+
_lib.spir_dlr2ir_zz.restype = c_int
|
|
253
|
+
|
|
254
|
+
# Release functions
|
|
255
|
+
_lib.spir_kernel_release.argtypes = [spir_kernel]
|
|
256
|
+
_lib.spir_kernel_release.restype = None
|
|
257
|
+
|
|
258
|
+
_lib.spir_sve_result_release.argtypes = [spir_sve_result]
|
|
259
|
+
_lib.spir_sve_result_release.restype = None
|
|
260
|
+
|
|
261
|
+
_lib.spir_basis_release.argtypes = [spir_basis]
|
|
262
|
+
_lib.spir_basis_release.restype = None
|
|
263
|
+
|
|
264
|
+
_lib.spir_funcs_release.argtypes = [spir_funcs]
|
|
265
|
+
_lib.spir_funcs_release.restype = None
|
|
266
|
+
|
|
267
|
+
_lib.spir_sampling_release.argtypes = [spir_sampling]
|
|
268
|
+
_lib.spir_sampling_release.restype = None
|
|
269
|
+
|
|
270
|
+
_setup_prototypes()
|
|
271
|
+
|
|
272
|
+
# Python wrapper functions
|
|
273
|
+
def logistic_kernel_new(lambda_val):
|
|
274
|
+
"""Create a new logistic kernel."""
|
|
275
|
+
status = c_int()
|
|
276
|
+
kernel = _lib.spir_logistic_kernel_new(lambda_val, byref(status))
|
|
277
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
278
|
+
raise RuntimeError(f"Failed to create logistic kernel: {status.value}")
|
|
279
|
+
return kernel
|
|
280
|
+
|
|
281
|
+
def reg_bose_kernel_new(lambda_val):
|
|
282
|
+
"""Create a new regularized bosonic kernel."""
|
|
283
|
+
status = c_int()
|
|
284
|
+
kernel = _lib.spir_reg_bose_kernel_new(lambda_val, byref(status))
|
|
285
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
286
|
+
raise RuntimeError(f"Failed to create regularized bosonic kernel: {status.value}")
|
|
287
|
+
return kernel
|
|
288
|
+
|
|
289
|
+
def sve_result_new(kernel, epsilon, cutoff=None, lmax=None, n_gauss=None, Twork=None):
|
|
290
|
+
"""Create a new SVE result."""
|
|
291
|
+
# Validate epsilon
|
|
292
|
+
if epsilon <= 0:
|
|
293
|
+
raise RuntimeError(f"Failed to create SVE result: epsilon must be positive, got {epsilon}")
|
|
294
|
+
|
|
295
|
+
if cutoff is None:
|
|
296
|
+
cutoff = -1.0
|
|
297
|
+
if lmax is None:
|
|
298
|
+
lmax = -1
|
|
299
|
+
if n_gauss is None:
|
|
300
|
+
n_gauss = -1
|
|
301
|
+
if Twork is None:
|
|
302
|
+
Twork = SPIR_TWORK_FLOAT64X2
|
|
303
|
+
|
|
304
|
+
status = c_int()
|
|
305
|
+
sve = _lib.spir_sve_result_new(kernel, epsilon, cutoff, lmax, n_gauss, Twork, byref(status))
|
|
306
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
307
|
+
raise RuntimeError(f"Failed to create SVE result: {status.value}")
|
|
308
|
+
return sve
|
|
309
|
+
|
|
310
|
+
def sve_result_get_size(sve):
|
|
311
|
+
"""Get the size of an SVE result."""
|
|
312
|
+
size = c_int()
|
|
313
|
+
status = _lib.spir_sve_result_get_size(sve, byref(size))
|
|
314
|
+
if status != COMPUTATION_SUCCESS:
|
|
315
|
+
raise RuntimeError(f"Failed to get SVE result size: {status}")
|
|
316
|
+
return size.value
|
|
317
|
+
|
|
318
|
+
def sve_result_get_svals(sve):
|
|
319
|
+
"""Get the singular values from an SVE result."""
|
|
320
|
+
size = sve_result_get_size(sve)
|
|
321
|
+
svals = np.zeros(size, dtype=np.float64)
|
|
322
|
+
status = _lib.spir_sve_result_get_svals(sve, svals.ctypes.data_as(POINTER(c_double)))
|
|
323
|
+
if status != COMPUTATION_SUCCESS:
|
|
324
|
+
raise RuntimeError(f"Failed to get singular values: {status}")
|
|
325
|
+
return svals
|
|
326
|
+
|
|
327
|
+
def basis_new(statistics, beta, omega_max, kernel, sve, max_size):
|
|
328
|
+
"""Create a new basis."""
|
|
329
|
+
status = c_int()
|
|
330
|
+
basis = _lib.spir_basis_new(
|
|
331
|
+
statistics, beta, omega_max, kernel, sve, max_size, byref(status)
|
|
332
|
+
)
|
|
333
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
334
|
+
raise RuntimeError(f"Failed to create basis: {status.value}")
|
|
335
|
+
return basis
|
|
336
|
+
|
|
337
|
+
def basis_get_size(basis):
|
|
338
|
+
"""Get the size of a basis."""
|
|
339
|
+
size = c_int()
|
|
340
|
+
status = _lib.spir_basis_get_size(basis, byref(size))
|
|
341
|
+
if status != COMPUTATION_SUCCESS:
|
|
342
|
+
raise RuntimeError(f"Failed to get basis size: {status}")
|
|
343
|
+
return size.value
|
|
344
|
+
|
|
345
|
+
def basis_get_svals(basis):
|
|
346
|
+
"""Get the singular values of a basis."""
|
|
347
|
+
size = basis_get_size(basis)
|
|
348
|
+
svals = np.zeros(size, dtype=np.float64)
|
|
349
|
+
status = _lib.spir_basis_get_svals(basis, svals.ctypes.data_as(POINTER(c_double)))
|
|
350
|
+
if status != COMPUTATION_SUCCESS:
|
|
351
|
+
raise RuntimeError(f"Failed to get singular values: {status}")
|
|
352
|
+
return svals
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def basis_get_stats(basis):
|
|
356
|
+
"""Get the statistics type of a basis."""
|
|
357
|
+
stats = c_int()
|
|
358
|
+
status = _lib.spir_basis_get_stats(basis, byref(stats))
|
|
359
|
+
if status != COMPUTATION_SUCCESS:
|
|
360
|
+
raise RuntimeError(f"Failed to get basis statistics: {status}")
|
|
361
|
+
return stats.value
|
|
362
|
+
|
|
363
|
+
def basis_get_u(basis):
|
|
364
|
+
"""Get the imaginary-time basis functions."""
|
|
365
|
+
status = c_int()
|
|
366
|
+
funcs = _lib.spir_basis_get_u(basis, byref(status))
|
|
367
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
368
|
+
raise RuntimeError(f"Failed to get u basis functions: {status.value}")
|
|
369
|
+
return funcs
|
|
370
|
+
|
|
371
|
+
def basis_get_v(basis):
|
|
372
|
+
"""Get the real-frequency basis functions."""
|
|
373
|
+
status = c_int()
|
|
374
|
+
funcs = _lib.spir_basis_get_v(basis, byref(status))
|
|
375
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
376
|
+
raise RuntimeError(f"Failed to get v basis functions: {status.value}")
|
|
377
|
+
return funcs
|
|
378
|
+
|
|
379
|
+
def basis_get_uhat(basis):
|
|
380
|
+
"""Get the Matsubara frequency basis functions."""
|
|
381
|
+
status = c_int()
|
|
382
|
+
funcs = _lib.spir_basis_get_uhat(basis, byref(status))
|
|
383
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
384
|
+
raise RuntimeError(f"Failed to get uhat basis functions: {status.value}")
|
|
385
|
+
return funcs
|
|
386
|
+
|
|
387
|
+
def funcs_get_size(funcs):
|
|
388
|
+
"""Get the size of a basis function set."""
|
|
389
|
+
size = c_int()
|
|
390
|
+
status = _lib.spir_funcs_get_size(funcs, byref(size))
|
|
391
|
+
if status != COMPUTATION_SUCCESS:
|
|
392
|
+
raise RuntimeError(f"Failed to get function size: {status}")
|
|
393
|
+
return size.value
|
|
394
|
+
|
|
395
|
+
# TODO: Rename funcs_eval_single
|
|
396
|
+
def funcs_eval_single_float64(funcs, x):
|
|
397
|
+
"""Evaluate basis functions at a single point."""
|
|
398
|
+
# Get number of functions
|
|
399
|
+
size = c_int()
|
|
400
|
+
status = _lib.spir_funcs_get_size(funcs, byref(size))
|
|
401
|
+
if status != COMPUTATION_SUCCESS:
|
|
402
|
+
raise RuntimeError(f"Failed to get function size: {status}")
|
|
403
|
+
|
|
404
|
+
# Prepare output array
|
|
405
|
+
out = np.zeros(size.value, dtype=np.float64)
|
|
406
|
+
|
|
407
|
+
# Evaluate
|
|
408
|
+
status = _lib.spir_funcs_eval(
|
|
409
|
+
funcs, c_double(x),
|
|
410
|
+
out.ctypes.data_as(POINTER(c_double))
|
|
411
|
+
)
|
|
412
|
+
if status != COMPUTATION_SUCCESS:
|
|
413
|
+
raise RuntimeError(f"Failed to evaluate functions: {status}")
|
|
414
|
+
|
|
415
|
+
return out
|
|
416
|
+
|
|
417
|
+
# TODO: Rename to funcs_eval_matsu_single
|
|
418
|
+
def funcs_eval_single_complex128(funcs, x):
|
|
419
|
+
"""Evaluate basis functions at a single point."""
|
|
420
|
+
# Get number of functions
|
|
421
|
+
size = c_int()
|
|
422
|
+
status = _lib.spir_funcs_get_size(funcs, byref(size))
|
|
423
|
+
if status != COMPUTATION_SUCCESS:
|
|
424
|
+
raise RuntimeError(f"Failed to get function size: {status}")
|
|
425
|
+
|
|
426
|
+
# Prepare output array
|
|
427
|
+
out = np.zeros(size.value, dtype=np.complex128)
|
|
428
|
+
|
|
429
|
+
# Evaluate
|
|
430
|
+
status = _lib.spir_funcs_eval_matsu(
|
|
431
|
+
funcs, c_int64(x),
|
|
432
|
+
out.ctypes.data_as(POINTER(c_double_complex))
|
|
433
|
+
)
|
|
434
|
+
if status != COMPUTATION_SUCCESS:
|
|
435
|
+
raise RuntimeError(f"Failed to evaluate functions: {status}")
|
|
436
|
+
|
|
437
|
+
return out
|
|
438
|
+
|
|
439
|
+
def funcs_get_n_roots(funcs):
|
|
440
|
+
"""Get the number of roots of the basis functions."""
|
|
441
|
+
n_roots = c_int()
|
|
442
|
+
status = _lib.spir_funcs_get_n_roots(funcs, byref(n_roots))
|
|
443
|
+
if status != COMPUTATION_SUCCESS:
|
|
444
|
+
raise RuntimeError(f"Failed to get number of roots: {status}")
|
|
445
|
+
return n_roots.value
|
|
446
|
+
|
|
447
|
+
def funcs_get_roots(funcs):
|
|
448
|
+
"""Get the roots of the basis functions."""
|
|
449
|
+
n_roots = funcs_get_n_roots(funcs)
|
|
450
|
+
roots = np.zeros(n_roots, dtype=np.float64)
|
|
451
|
+
status = _lib.spir_funcs_get_roots(funcs, roots.ctypes.data_as(POINTER(c_double)))
|
|
452
|
+
if status != COMPUTATION_SUCCESS:
|
|
453
|
+
raise RuntimeError(f"Failed to get roots: {status}")
|
|
454
|
+
return roots
|
|
455
|
+
|
|
456
|
+
def basis_get_default_tau_sampling_points(basis):
|
|
457
|
+
"""Get default tau sampling points for a basis."""
|
|
458
|
+
# Get number of points
|
|
459
|
+
n_points = c_int()
|
|
460
|
+
status = _lib.spir_basis_get_n_default_taus(basis, byref(n_points))
|
|
461
|
+
if status != COMPUTATION_SUCCESS:
|
|
462
|
+
raise RuntimeError(f"Failed to get number of default tau points: {status}")
|
|
463
|
+
|
|
464
|
+
# Get the points
|
|
465
|
+
points = np.zeros(n_points.value, dtype=np.float64)
|
|
466
|
+
status = _lib.spir_basis_get_default_taus(basis, points.ctypes.data_as(POINTER(c_double)))
|
|
467
|
+
if status != COMPUTATION_SUCCESS:
|
|
468
|
+
raise RuntimeError(f"Failed to get default tau points: {status}")
|
|
469
|
+
|
|
470
|
+
return points
|
|
471
|
+
|
|
472
|
+
def basis_get_default_tau_sampling_points_ext(basis, n_points):
|
|
473
|
+
"""Get default tau sampling points for a basis."""
|
|
474
|
+
points = np.zeros(n_points, dtype=np.float64)
|
|
475
|
+
n_points_returned = c_int()
|
|
476
|
+
status = _lib.spir_basis_get_default_taus_ext(basis, n_points, points.ctypes.data_as(POINTER(c_double)), byref(n_points_returned))
|
|
477
|
+
if status != COMPUTATION_SUCCESS:
|
|
478
|
+
raise RuntimeError(f"Failed to get default tau points: {status}")
|
|
479
|
+
return points
|
|
480
|
+
|
|
481
|
+
def basis_get_default_omega_sampling_points(basis):
|
|
482
|
+
"""Get default omega (real frequency) sampling points for a basis."""
|
|
483
|
+
# Get number of points
|
|
484
|
+
n_points = c_int()
|
|
485
|
+
status = _lib.spir_basis_get_n_default_ws(basis, byref(n_points))
|
|
486
|
+
if status != COMPUTATION_SUCCESS:
|
|
487
|
+
raise RuntimeError(f"Failed to get number of default omega points: {status}")
|
|
488
|
+
|
|
489
|
+
# Get the points
|
|
490
|
+
points = np.zeros(n_points.value, dtype=np.float64)
|
|
491
|
+
status = _lib.spir_basis_get_default_ws(basis, points.ctypes.data_as(POINTER(c_double)))
|
|
492
|
+
if status != COMPUTATION_SUCCESS:
|
|
493
|
+
raise RuntimeError(f"Failed to get default omega points: {status}")
|
|
494
|
+
|
|
495
|
+
return points
|
|
496
|
+
|
|
497
|
+
def basis_get_default_matsubara_sampling_points(basis, positive_only=False):
|
|
498
|
+
"""Get default Matsubara sampling points for a basis."""
|
|
499
|
+
# Get number of points
|
|
500
|
+
n_points = c_int()
|
|
501
|
+
status = _lib.spir_basis_get_n_default_matsus(basis, c_bool(positive_only), byref(n_points))
|
|
502
|
+
if status != COMPUTATION_SUCCESS:
|
|
503
|
+
raise RuntimeError(f"Failed to get number of default Matsubara points: {status}")
|
|
504
|
+
|
|
505
|
+
# Get the points
|
|
506
|
+
points = np.zeros(n_points.value, dtype=np.int64)
|
|
507
|
+
status = _lib.spir_basis_get_default_matsus(basis, c_bool(positive_only), points.ctypes.data_as(POINTER(c_int64)))
|
|
508
|
+
if status != COMPUTATION_SUCCESS:
|
|
509
|
+
raise RuntimeError(f"Failed to get default Matsubara points: {status}")
|
|
510
|
+
|
|
511
|
+
return points
|
|
512
|
+
|
|
513
|
+
def basis_get_n_default_matsus_ext(basis, n_points, positive_only):
|
|
514
|
+
"""Get the number of default Matsubara sampling points for a basis."""
|
|
515
|
+
n_points_returned = c_int()
|
|
516
|
+
status = _lib.spir_basis_get_n_default_matsus_ext(basis, c_bool(positive_only), n_points, byref(n_points_returned))
|
|
517
|
+
if status != COMPUTATION_SUCCESS:
|
|
518
|
+
raise RuntimeError(f"Failed to get number of default Matsubara points: {status}")
|
|
519
|
+
return n_points_returned.value
|
|
520
|
+
|
|
521
|
+
def basis_get_default_matsus_ext(basis, positive_only, points):
|
|
522
|
+
n_points = len(points)
|
|
523
|
+
n_points_returned = c_int()
|
|
524
|
+
status = _lib.spir_basis_get_default_matsus_ext(basis, c_bool(positive_only), n_points, points.ctypes.data_as(POINTER(c_int64)), byref(n_points_returned))
|
|
525
|
+
if status != COMPUTATION_SUCCESS:
|
|
526
|
+
raise RuntimeError(f"Failed to get default Matsubara points: {status}")
|
|
527
|
+
return points
|
|
528
|
+
|
|
529
|
+
def tau_sampling_new(basis, sampling_points=None):
|
|
530
|
+
"""Create a new tau sampling object."""
|
|
531
|
+
if sampling_points is None:
|
|
532
|
+
sampling_points = basis_get_default_tau_sampling_points(basis)
|
|
533
|
+
|
|
534
|
+
sampling_points = np.asarray(sampling_points, dtype=np.float64)
|
|
535
|
+
n_points = len(sampling_points)
|
|
536
|
+
|
|
537
|
+
status = c_int()
|
|
538
|
+
sampling = _lib.spir_tau_sampling_new(
|
|
539
|
+
basis, n_points,
|
|
540
|
+
sampling_points.ctypes.data_as(POINTER(c_double)),
|
|
541
|
+
byref(status)
|
|
542
|
+
)
|
|
543
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
544
|
+
raise RuntimeError(f"Failed to create tau sampling: {status.value}")
|
|
545
|
+
|
|
546
|
+
return sampling
|
|
547
|
+
|
|
548
|
+
def _statistics_to_c(statistics):
|
|
549
|
+
"""Convert statistics to c type."""
|
|
550
|
+
if statistics == "F":
|
|
551
|
+
return SPIR_STATISTICS_FERMIONIC
|
|
552
|
+
elif statistics == "B":
|
|
553
|
+
return SPIR_STATISTICS_BOSONIC
|
|
554
|
+
else:
|
|
555
|
+
raise ValueError(f"Invalid statistics: {statistics}")
|
|
556
|
+
|
|
557
|
+
def tau_sampling_new_with_matrix(basis, statistics, sampling_points, matrix):
|
|
558
|
+
"""Create a new tau sampling object with a matrix."""
|
|
559
|
+
status = c_int()
|
|
560
|
+
sampling = _lib.spir_tau_sampling_new_with_matrix(
|
|
561
|
+
SPIR_ORDER_ROW_MAJOR,
|
|
562
|
+
_statistics_to_c(statistics),
|
|
563
|
+
basis.size,
|
|
564
|
+
sampling_points.size,
|
|
565
|
+
sampling_points.ctypes.data_as(POINTER(c_double)),
|
|
566
|
+
matrix.ctypes.data_as(POINTER(c_double)),
|
|
567
|
+
byref(status)
|
|
568
|
+
)
|
|
569
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
570
|
+
raise RuntimeError(f"Failed to create tau sampling: {status.value}")
|
|
571
|
+
|
|
572
|
+
return sampling
|
|
573
|
+
|
|
574
|
+
def matsubara_sampling_new(basis, positive_only=False, sampling_points=None):
|
|
575
|
+
"""Create a new Matsubara sampling object."""
|
|
576
|
+
if sampling_points is None:
|
|
577
|
+
sampling_points = basis_get_default_matsubara_sampling_points(basis, positive_only)
|
|
578
|
+
|
|
579
|
+
sampling_points = np.asarray(sampling_points, dtype=np.int64)
|
|
580
|
+
n_points = len(sampling_points)
|
|
581
|
+
|
|
582
|
+
status = c_int()
|
|
583
|
+
sampling = _lib.spir_matsu_sampling_new(
|
|
584
|
+
basis, c_bool(positive_only), n_points,
|
|
585
|
+
sampling_points.ctypes.data_as(POINTER(c_int64)),
|
|
586
|
+
byref(status)
|
|
587
|
+
)
|
|
588
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
589
|
+
raise RuntimeError(f"Failed to create Matsubara sampling: {status.value}")
|
|
590
|
+
|
|
591
|
+
return sampling
|
|
592
|
+
|
|
593
|
+
def matsubara_sampling_new_with_matrix(statistics, basis_size, positive_only, sampling_points, matrix):
|
|
594
|
+
"""Create a new Matsubara sampling object with a matrix."""
|
|
595
|
+
status = c_int()
|
|
596
|
+
sampling = _lib.spir_matsu_sampling_new_with_matrix(
|
|
597
|
+
SPIR_ORDER_ROW_MAJOR, # order
|
|
598
|
+
_statistics_to_c(statistics), # statistics
|
|
599
|
+
c_int(basis_size), # basis_size
|
|
600
|
+
c_bool(positive_only), # positive_only
|
|
601
|
+
c_int(len(sampling_points)), # num_points
|
|
602
|
+
sampling_points.ctypes.data_as(POINTER(c_int64)), # points
|
|
603
|
+
matrix.ctypes.data_as(POINTER(c_double_complex)), # matrix
|
|
604
|
+
byref(status) # status
|
|
605
|
+
)
|
|
606
|
+
if status.value != COMPUTATION_SUCCESS:
|
|
607
|
+
raise RuntimeError(f"Failed to create Matsubara sampling: {status.value}")
|
|
608
|
+
|
|
609
|
+
return sampling
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type definitions for the SparseIR C API.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from ctypes import *
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
# Define complex type
|
|
9
|
+
c_complex = c_double * 2
|
|
10
|
+
|
|
11
|
+
# Opaque types
|
|
12
|
+
class _spir_kernel(Structure):
|
|
13
|
+
_fields_ = []
|
|
14
|
+
|
|
15
|
+
class _spir_funcs(Structure):
|
|
16
|
+
_fields_ = []
|
|
17
|
+
|
|
18
|
+
class _spir_basis(Structure):
|
|
19
|
+
_fields_ = []
|
|
20
|
+
|
|
21
|
+
class _spir_sampling(Structure):
|
|
22
|
+
_fields_ = []
|
|
23
|
+
|
|
24
|
+
class _spir_sve_result(Structure):
|
|
25
|
+
_fields_ = []
|
|
26
|
+
|
|
27
|
+
# Type aliases
|
|
28
|
+
spir_kernel = POINTER(_spir_kernel)
|
|
29
|
+
spir_funcs = POINTER(_spir_funcs)
|
|
30
|
+
spir_basis = POINTER(_spir_basis)
|
|
31
|
+
spir_sampling = POINTER(_spir_sampling)
|
|
32
|
+
spir_sve_result = POINTER(_spir_sve_result)
|
|
33
|
+
|
|
34
|
+
# Additional ctypes definitions
|
|
35
|
+
c_int64 = c_longlong
|
|
36
|
+
|
|
37
|
+
# NumPy dtype mappings
|
|
38
|
+
COMPLEX_DTYPE = np.dtype(np.complex128)
|
|
39
|
+
DOUBLE_DTYPE = np.dtype(np.float64)
|
|
40
|
+
INT64_DTYPE = np.dtype(np.int64)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pylibsparseir
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python bindings for the libsparseir library, providing efficient sparse intermediate representation for many-body physics calculations
|
|
5
|
+
Author: SpM-lab
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/SpM-lab/libsparseir
|
|
8
|
+
Project-URL: Repository, https://github.com/SpM-lab/libsparseir
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/SpM-lab/libsparseir/issues
|
|
10
|
+
Keywords: physics,many-body,green-functions,sparse-ir
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: numpy
|
|
19
|
+
Requires-Dist: scipy
|
|
20
|
+
|
|
21
|
+
# Python bindings for libsparseir
|
|
22
|
+
|
|
23
|
+
This is a low-level binding for the [libsparseir](https://github.com/SpM-lab/libsparseir) library.
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
- Python >= 3.10
|
|
28
|
+
- CMake (for building the C++ library)
|
|
29
|
+
- C++11 compatible compiler
|
|
30
|
+
- numpy
|
|
31
|
+
|
|
32
|
+
### Optional Dependencies
|
|
33
|
+
|
|
34
|
+
- **OpenBLAS** (recommended for better performance)
|
|
35
|
+
- macOS: `brew install openblas`
|
|
36
|
+
- Ubuntu/Debian: `sudo apt install libopenblas-dev`
|
|
37
|
+
- CentOS/RHEL: `sudo yum install openblas-devel`
|
|
38
|
+
|
|
39
|
+
## Build
|
|
40
|
+
|
|
41
|
+
### Install Dependencies and Build
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uv sync
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This will:
|
|
48
|
+
- Install Python dependencies (numpy)
|
|
49
|
+
- Build the C++ libsparseir library using CMake
|
|
50
|
+
- Install the Python package in development mode
|
|
51
|
+
|
|
52
|
+
### Build with OpenBLAS Support
|
|
53
|
+
|
|
54
|
+
To enable OpenBLAS support for improved performance:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Set environment variable to enable BLAS
|
|
58
|
+
export SPARSEIR_USE_BLAS=1
|
|
59
|
+
uv sync
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or for a single build:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
SPARSEIR_USE_BLAS=1 uv sync
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The build system will automatically detect OpenBLAS if it's installed in standard locations. If OpenBLAS is installed in a custom location, you may need to set additional environment variables:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
export CMAKE_PREFIX_PATH="/path/to/openblas"
|
|
72
|
+
export SPARSEIR_USE_BLAS=1
|
|
73
|
+
uv sync
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Clean Build Artifacts
|
|
77
|
+
|
|
78
|
+
To remove build artifacts and files copied from the parent directory:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
uv run clean
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
This will remove:
|
|
85
|
+
- Build directories: `build/`, `dist/`, `*.egg-info`
|
|
86
|
+
- Copied source files: `include/`, `src/`, `fortran/`, `cmake/`, `CMakeLists.txt`
|
|
87
|
+
- Compiled libraries: `pylibsparseir/*.so`, `pylibsparseir/*.dylib`, `pylibsparseir/*.dll`
|
|
88
|
+
- Cache directories: `pylibsparseir/__pycache__`
|
|
89
|
+
|
|
90
|
+
## Performance Notes
|
|
91
|
+
|
|
92
|
+
### BLAS Support
|
|
93
|
+
|
|
94
|
+
This package supports BLAS libraries for improved linear algebra performance:
|
|
95
|
+
|
|
96
|
+
- **With OpenBLAS**: Significant performance improvements for matrix operations
|
|
97
|
+
- **Without BLAS**: Uses Eigen's built-in implementations (still efficient, but slower for large matrices)
|
|
98
|
+
|
|
99
|
+
The build system will automatically detect and use OpenBLAS if available. You can verify BLAS support by checking the build output for messages like:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
BLAS support enabled
|
|
103
|
+
Found OpenBLAS at: /opt/homebrew/opt/openblas
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Troubleshooting
|
|
107
|
+
|
|
108
|
+
**Build fails with "Could NOT find BLAS":**
|
|
109
|
+
```bash
|
|
110
|
+
# Install OpenBLAS first
|
|
111
|
+
brew install openblas # macOS
|
|
112
|
+
sudo apt install libopenblas-dev # Ubuntu
|
|
113
|
+
|
|
114
|
+
# Then force BLAS detection
|
|
115
|
+
SPARSEIR_USE_BLAS=1 uv sync
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**OpenBLAS not detected automatically:**
|
|
119
|
+
```bash
|
|
120
|
+
# Set CMake prefix path manually
|
|
121
|
+
export CMAKE_PREFIX_PATH="/usr/local/opt/openblas" # or your OpenBLAS path
|
|
122
|
+
export SPARSEIR_USE_BLAS=1
|
|
123
|
+
uv sync
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Verify BLAS support in built package:**
|
|
127
|
+
```python
|
|
128
|
+
import pylibsparseir
|
|
129
|
+
# Check build logs or library dependencies to confirm BLAS linking
|
|
130
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
pylibsparseir/clean_build_artifacts.py,sha256=Wbfe_zlZB5T04pXR8rvRAvsaLMYl6Y61p77W-eRKUME,2079
|
|
2
|
+
pylibsparseir/constants.py,sha256=Ek3JnmgiDWy3LB8f_9QA7Gh0ReaEC-W2MlCBJG3cBYg,864
|
|
3
|
+
pylibsparseir/core.py,sha256=37sGLY_Gbddf3x-kScoJtmyaLOeDOFaPbBCMPIMLOP0,23647
|
|
4
|
+
pylibsparseir/ctypes_wrapper.py,sha256=G6_eraRUh9ON_2e_v4U_hc34HXirlotoawQDOkS0my0,798
|
|
5
|
+
pylibsparseir/libsparseir.so,sha256=6omR8CC3JpC-9lIqHq4nROMFVH40cf5vA4juxx74WjI,2242576
|
|
6
|
+
pylibsparseir/libsparseir.so.0,sha256=6omR8CC3JpC-9lIqHq4nROMFVH40cf5vA4juxx74WjI,2242576
|
|
7
|
+
pylibsparseir/libsparseir.so.0.4.2,sha256=6omR8CC3JpC-9lIqHq4nROMFVH40cf5vA4juxx74WjI,2242576
|
|
8
|
+
pylibsparseir-0.1.0.dist-info/METADATA,sha256=CItKxoGfymHNuwhCTxzA66svXd_uU4dgBHU-r8JYcVA,3585
|
|
9
|
+
pylibsparseir-0.1.0.dist-info/WHEEL,sha256=Obtqci3x5vy5ZivY2BiOH9GHO8-xQ0d4HFhTOtXMNhw,152
|
|
10
|
+
pylibsparseir-0.1.0.dist-info/entry_points.txt,sha256=0XwdYIQ1lPtI8228zUo7BpvdnwOzqct0cc6gp3r18pA,84
|
|
11
|
+
pylibsparseir-0.1.0.dist-info/top_level.txt,sha256=eKNiduo4CIO59083m_BjY8uBZ9Fp1D3t8hkU4-k2waA,14
|
|
12
|
+
pylibsparseir-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pylibsparseir
|