blocksolver 0.8.2__cp39-cp39-win_amd64.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.
@@ -0,0 +1,437 @@
1
+ Metadata-Version: 2.1
2
+ Name: blocksolver
3
+ Version: 0.8.2
4
+ Summary: Block Quasi-Minimal-Residual sparse linear solver
5
+ Keywords: sparse,linear-algebra,iterative-solver,qmr,fortran,umfpack
6
+ Author-Email: Qianqian Fang <q.fang@neu.edu>
7
+ License: BSD-3-Clause OR LGPL-3.0-or-later OR GPL-3.0-or-later
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: License :: OSI Approved :: BSD License
11
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
12
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Programming Language :: Fortran
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
26
+ Project-URL: Homepage, https://blit.sourceforge.net
27
+ Project-URL: Repository, https://github.com/fangq/blocksolver
28
+ Project-URL: Documentation, https://blit.sourceforge.net
29
+ Project-URL: Bug Tracker, https://github.com/fangq/blocksolver/issues
30
+ Requires-Python: >=3.8
31
+ Requires-Dist: numpy>=1.20
32
+ Requires-Dist: scipy>=1.0
33
+ Provides-Extra: fast
34
+ Requires-Dist: numba>=0.50; extra == "fast"
35
+ Provides-Extra: test
36
+ Requires-Dist: pytest>=6.0; extra == "test"
37
+ Provides-Extra: dev
38
+ Requires-Dist: pytest>=6.0; extra == "dev"
39
+ Requires-Dist: build; extra == "dev"
40
+ Requires-Dist: twine; extra == "dev"
41
+ Description-Content-Type: text/markdown
42
+
43
+ # BlockSolver - Block Quasi-Minimal Residual (BLQMR) Sparse Linear Solver
44
+
45
+ **BlockSolver** is a Python package for solving large sparse linear systems using the Block Quasi-Minimal Residual (BLQMR) algorithm. It provides both a high-performance Fortran backend and a pure Python/NumPy implementation for maximum portability.
46
+
47
+ ## Features
48
+
49
+ - **Block QMR Algorithm**: Efficiently solves multiple right-hand sides simultaneously
50
+ - **Complex Symmetric Support**: Designed for complex symmetric matrices (A = Aᵀ, not A = A†)
51
+ - **Dual Backend**: Fortran extension for speed, Python fallback for portability
52
+ - **ILU Preconditioning**: Built-in incomplete LU preconditioner for faster convergence
53
+ - **SciPy Integration**: Works seamlessly with SciPy sparse matrices
54
+ - **Optional Numba Acceleration**: JIT-compiled kernels for the Python backend
55
+
56
+ ## Algorithm
57
+
58
+ ### Block Quasi-Minimal Residual (BLQMR)
59
+
60
+ The BLQMR algorithm is an iterative Krylov subspace method specifically designed for:
61
+
62
+ 1. **Complex symmetric systems**: Unlike standard methods that assume Hermitian (A = A†) or general matrices, BLQMR exploits complex symmetry (A = Aᵀ) which arises in electromagnetics, acoustics, and diffuse optical tomography.
63
+
64
+ 2. **Multiple right-hand sides**: Instead of solving each system independently, BLQMR processes all right-hand sides together in a block fashion, sharing Krylov subspace information and reducing total computation.
65
+
66
+ 3. **Quasi-minimal residual**: The algorithm minimizes a quasi-residual norm at each iteration, providing smooth convergence without the erratic behavior of some Krylov methods.
67
+
68
+ ### Key Components
69
+
70
+ - **Quasi-QR Decomposition**: A modified Gram-Schmidt process using the quasi inner product ⟨x,y⟩ = Σ xₖyₖ (without conjugation) for complex symmetric systems.
71
+
72
+ - **Three-term Lanczos Recurrence**: Builds an orthonormal basis for the Krylov subspace with short recurrences, minimizing memory usage.
73
+
74
+ - **Block Updates**: Processes m right-hand sides simultaneously, with typical block sizes of 1-16.
75
+
76
+ ### When to Use BLQMR
77
+
78
+ | Use Case | Recommendation |
79
+ |----------|----------------|
80
+ | Complex symmetric matrix (A = Aᵀ) | ✅ Ideal |
81
+ | Multiple right-hand sides | ✅ Ideal |
82
+ | Real symmetric positive definite | Consider CG first |
83
+ | General non-symmetric | Consider GMRES or BiCGSTAB |
84
+ | Very large systems (>10⁶ unknowns) | ✅ Good with preconditioning |
85
+
86
+ ## Installation
87
+
88
+ ### From PyPI
89
+
90
+ ```bash
91
+ pip install blocksolver
92
+ ```
93
+
94
+ ### From Source
95
+
96
+ Prerequisites:
97
+ - Python ≥ 3.8
98
+ - NumPy ≥ 1.20
99
+ - SciPy ≥ 1.0
100
+ - (Optional) Fortran compiler + UMFPACK for the accelerated backend
101
+ - (Optional) Numba for accelerated Python backend
102
+
103
+ ```bash
104
+ # Ubuntu/Debian
105
+ sudo apt install gfortran libsuitesparse-dev libblas-dev liblapack-dev
106
+
107
+ # macOS
108
+ brew install gcc suite-sparse openblas
109
+
110
+ # Install
111
+ cd python
112
+ pip install .
113
+ ```
114
+
115
+ ## Quick Start
116
+
117
+ ```python
118
+ import numpy as np
119
+ from scipy.sparse import csc_matrix
120
+ from blocksolver import blqmr
121
+
122
+ # Create a sparse matrix
123
+ A = csc_matrix([
124
+ [4, 1, 0, 0],
125
+ [1, 4, 1, 0],
126
+ [0, 1, 4, 1],
127
+ [0, 0, 1, 4]
128
+ ], dtype=float)
129
+
130
+ b = np.array([1., 2., 3., 4.])
131
+
132
+ # Solve Ax = b
133
+ result = blqmr(A, b, tol=1e-10)
134
+
135
+ print(f"Solution: {result.x}")
136
+ print(f"Converged: {result.converged}")
137
+ print(f"Iterations: {result.iter}")
138
+ print(f"Relative residual: {result.relres:.2e}")
139
+ ```
140
+
141
+ ## Usage
142
+
143
+ ### Main Interface: `blqmr()`
144
+
145
+ The primary function `blqmr()` automatically selects the best available backend (Fortran if available, otherwise Python).
146
+
147
+ ```python
148
+ from blocksolver import blqmr, BLQMR_EXT
149
+
150
+ # Check which backend is active
151
+ print(f"Using Fortran backend: {BLQMR_EXT}")
152
+
153
+ # Basic usage
154
+ result = blqmr(A, b)
155
+
156
+ # With options
157
+ result = blqmr(A, b,
158
+ tol=1e-8, # Convergence tolerance
159
+ maxiter=1000, # Maximum iterations
160
+ use_precond=True, # Use ILU preconditioning
161
+ )
162
+ ```
163
+
164
+ ### Multiple Right-Hand Sides
165
+
166
+ BLQMR excels when solving the same system with multiple right-hand sides:
167
+
168
+ ```python
169
+ import numpy as np
170
+ from blocksolver import blqmr
171
+
172
+ # 100 different right-hand sides
173
+ B = np.random.randn(n, 100)
174
+
175
+ # Solve all systems at once (much faster than solving individually)
176
+ result = blqmr(A, B, tol=1e-8)
177
+
178
+ # result.x has shape (n, 100)
179
+ ```
180
+
181
+ ### Complex Symmetric Systems
182
+
183
+ BLQMR is specifically designed for complex symmetric matrices (common in frequency-domain wave problems):
184
+
185
+ ```python
186
+ import numpy as np
187
+ from blocksolver import blqmr
188
+
189
+ # Complex symmetric matrix (A = A.T, NOT A.conj().T)
190
+ A = create_helmholtz_matrix(frequency=1000) # Your application
191
+ b = np.complex128(source_term)
192
+
193
+ result = blqmr(A, b, tol=1e-8)
194
+ ```
195
+
196
+ ### Custom Preconditioning
197
+
198
+ For the Python backend, you can provide custom preconditioners:
199
+
200
+ ```python
201
+ from blocksolver import blqmr, make_preconditioner
202
+
203
+ # Create ILU preconditioner
204
+ M1 = make_preconditioner(A, 'ilu')
205
+
206
+ # Or diagonal (Jacobi) preconditioner
207
+ M1 = make_preconditioner(A, 'diag')
208
+
209
+ # Solve with custom preconditioner
210
+ result = blqmr(A, b, M1=M1, use_precond=False)
211
+ ```
212
+
213
+ ### SciPy-Compatible Interface
214
+
215
+ For drop-in replacement in existing code:
216
+
217
+ ```python
218
+ from blocksolver import blqmr_scipy
219
+
220
+ # Returns (x, flag) like scipy.sparse.linalg solvers
221
+ x, flag = blqmr_scipy(A, b, tol=1e-10)
222
+ ```
223
+
224
+ ### Low-Level CSC Interface
225
+
226
+ For maximum control, use the CSC component interface:
227
+
228
+ ```python
229
+ from blocksolver import blqmr_solve
230
+
231
+ # CSC format components (0-based indexing)
232
+ Ap = np.array([0, 2, 5, 9, 10, 12], dtype=np.int32) # Column pointers
233
+ Ai = np.array([0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4], dtype=np.int32) # Row indices
234
+ Ax = np.array([2., 3., 3., -1., 4., 4., -3., 1., 2., 2., 6., 1.]) # Values
235
+ b = np.array([8., 45., -3., 3., 19.])
236
+
237
+ result = blqmr_solve(Ap, Ai, Ax, b,
238
+ tol=1e-8,
239
+ droptol=0.001, # ILU drop tolerance (Fortran only)
240
+ use_precond=True,
241
+ zero_based=True, # 0-based indexing (default)
242
+ )
243
+ ```
244
+
245
+ ## API Reference
246
+
247
+ ### `blqmr(A, B, **kwargs) -> BLQMRResult`
248
+
249
+ Main solver interface.
250
+
251
+ **Parameters:**
252
+ | Parameter | Type | Default | Description |
253
+ |-----------|------|---------|-------------|
254
+ | `A` | sparse matrix or ndarray | required | System matrix (n × n) |
255
+ | `B` | ndarray | required | Right-hand side (n,) or (n × m) |
256
+ | `tol` | float | 1e-6 | Convergence tolerance |
257
+ | `maxiter` | int | n | Maximum iterations |
258
+ | `M1`, `M2` | preconditioner | None | Custom preconditioners (Python backend) |
259
+ | `x0` | ndarray | None | Initial guess |
260
+ | `use_precond` | bool | True | Use ILU preconditioning |
261
+ | `droptol` | float | 0.001 | ILU drop tolerance (Fortran backend) |
262
+ | `residual` | bool | False | Use true residual for convergence (Python) |
263
+ | `workspace` | BLQMRWorkspace | None | Pre-allocated workspace (Python) |
264
+
265
+ **Returns:** `BLQMRResult` object with:
266
+ | Attribute | Type | Description |
267
+ |-----------|------|-------------|
268
+ | `x` | ndarray | Solution vector(s) |
269
+ | `flag` | int | 0=converged, 1=maxiter, 2=precond fail, 3=stagnation |
270
+ | `iter` | int | Iterations performed |
271
+ | `relres` | float | Final relative residual |
272
+ | `converged` | bool | True if flag == 0 |
273
+ | `resv` | ndarray | Residual history (Python backend only) |
274
+
275
+ ### `blqmr_solve(Ap, Ai, Ax, b, **kwargs) -> BLQMRResult`
276
+
277
+ Low-level CSC interface.
278
+
279
+ ### `blqmr_solve_multi(Ap, Ai, Ax, B, **kwargs) -> BLQMRResult`
280
+
281
+ Multiple right-hand sides with CSC input.
282
+
283
+ ### `blqmr_scipy(A, b, **kwargs) -> Tuple[ndarray, int]`
284
+
285
+ SciPy-compatible interface returning `(x, flag)`.
286
+
287
+ ### `make_preconditioner(A, type) -> Preconditioner`
288
+
289
+ Create a preconditioner for the Python backend.
290
+
291
+ **Types:** `'diag'`/`'jacobi'`, `'ilu'`/`'ilu0'`, `'ssor'`
292
+
293
+ ### Utility Functions
294
+
295
+ ```python
296
+ from blocksolver import (
297
+ BLQMR_EXT, # True if Fortran backend available
298
+ HAS_NUMBA, # True if Numba acceleration available
299
+ get_backend_info, # Returns dict with backend details
300
+ test, # Run built-in tests
301
+ )
302
+ ```
303
+
304
+ ## Performance Tips
305
+
306
+ 1. **Use the Fortran backend** when available (10-100× faster than Python)
307
+
308
+ 2. **Enable preconditioning** for ill-conditioned systems:
309
+ ```python
310
+ result = blqmr(A, b, use_precond=True)
311
+ ```
312
+
313
+ 3. **Batch multiple right-hand sides** instead of solving one at a time:
314
+ ```python
315
+ # Fast: single call with all RHS
316
+ result = blqmr(A, B_matrix)
317
+
318
+ # Slow: multiple calls
319
+ for b in B_columns:
320
+ result = blqmr(A, b)
321
+ ```
322
+
323
+ 4. **Install Numba** for faster Python backend:
324
+ ```bash
325
+ pip install numba
326
+ ```
327
+
328
+ 5. **Reuse workspace** for repeated solves with the same dimensions:
329
+ ```python
330
+ from blocksolver import BLQMRWorkspace
331
+ ws = BLQMRWorkspace(n, m)
332
+ for b in many_rhs:
333
+ result = blqmr(A, b, workspace=ws)
334
+ ```
335
+
336
+ ## Examples
337
+
338
+ ### Diffuse Optical Tomography
339
+
340
+ ```python
341
+ import numpy as np
342
+ from scipy.sparse import diags, kron, eye
343
+ from blocksolver import blqmr
344
+
345
+ def create_diffusion_matrix(nx, ny, D=1.0, mu_a=0.01, omega=1e9):
346
+ """Create 2D diffusion matrix for DOT."""
347
+ n = nx * ny
348
+ h = 1.0 / nx
349
+
350
+ # Laplacian
351
+ Lx = diags([-1, 2, -1], [-1, 0, 1], shape=(nx, nx)) / h**2
352
+ Ly = diags([-1, 2, -1], [-1, 0, 1], shape=(ny, ny)) / h**2
353
+ L = kron(eye(ny), Lx) + kron(Ly, eye(nx))
354
+
355
+ # Diffusion equation: (-D∇² + μ_a + iω/c) φ = q
356
+ c = 3e10 # speed of light in tissue (cm/s)
357
+ A = -D * L + mu_a * eye(n) + 1j * omega / c * eye(n)
358
+
359
+ return A.tocsc()
360
+
361
+ # Setup problem
362
+ A = create_diffusion_matrix(100, 100, omega=2*np.pi*100e6)
363
+ sources = np.random.randn(10000, 16) # 16 source positions
364
+
365
+ # Solve for all sources at once
366
+ result = blqmr(A, sources, tol=1e-8)
367
+ print(f"Solved {sources.shape[1]} systems in {result.iter} iterations")
368
+ ```
369
+
370
+ ### Frequency-Domain Acoustics
371
+
372
+ ```python
373
+ import numpy as np
374
+ from blocksolver import blqmr
375
+
376
+ # Helmholtz equation: (∇² + k²)p = f
377
+ # Results in complex symmetric matrix
378
+
379
+ def solve_helmholtz(K, M, f, frequencies):
380
+ """Solve Helmholtz at multiple frequencies."""
381
+ solutions = []
382
+ for omega in frequencies:
383
+ # A = K - ω²M (complex symmetric if K, M are symmetric)
384
+ A = K - omega**2 * M
385
+ result = blqmr(A, f, tol=1e-10)
386
+ solutions.append(result.x)
387
+ return np.array(solutions)
388
+ ```
389
+
390
+ ## Troubleshooting
391
+
392
+ ### "No Fortran backend available"
393
+
394
+ Install the package with Fortran support:
395
+ ```bash
396
+ # Install dependencies first
397
+ sudo apt install gfortran libsuitesparse-dev # Linux
398
+ brew install gcc suite-sparse # macOS
399
+
400
+ # Reinstall blocksolver
401
+ pip install --no-cache-dir blocksolver
402
+ ```
403
+
404
+ ### Slow convergence
405
+
406
+ 1. Enable preconditioning: `use_precond=True`
407
+ 2. Reduce ILU drop tolerance: `droptol=1e-4` (Fortran backend)
408
+ 3. Check matrix conditioning with `np.linalg.cond(A.toarray())`
409
+
410
+ ### Memory issues with large systems
411
+
412
+ 1. Use the Fortran backend (more memory efficient)
413
+ 2. Reduce block size for multiple RHS
414
+ 3. Use iterative refinement instead of tighter tolerance
415
+
416
+ ## License
417
+
418
+ BSD-3-Clause / LGPL-3.0+ / GPL-3.0+ (tri-licensed)
419
+
420
+ ## Citation
421
+
422
+ If you use BlockSolver in your research, please cite:
423
+
424
+ ```bibtex
425
+ @software{blocksolver,
426
+ author = {Qianqian Fang},
427
+ title = {BlockSolver: Block Quasi-Minimal Residual Sparse Linear Solver},
428
+ url = {https://github.com/fangq/blit},
429
+ year = {2024}
430
+ }
431
+ ```
432
+
433
+ ## See Also
434
+
435
+ - [BLIT](https://github.com/fangq/blit) - The underlying Fortran library
436
+ - [SciPy sparse.linalg](https://docs.scipy.org/doc/scipy/reference/sparse.linalg.html) - Other iterative solvers
437
+ - [PyAMG](https://github.com/pyamg/pyamg) - Algebraic multigrid solvers
@@ -0,0 +1,7 @@
1
+ blocksolver-0.8.2.dist-info/METADATA,sha256=v05b9IAmx9fbUkF3hB6OmY354Bnt-uzv4FNqJmXRhuM,13264
2
+ blocksolver-0.8.2.dist-info/WHEEL,sha256=8AdrFzOtKQ6LLJ-VyqCU3y1iN8N--fMXYqrdkeTKDn0,83
3
+ blocksolver/_blqmr.cp39-win_amd64.pyd,sha256=Sa4zNFSd8FQ6QwcWOyJ7jVMWepd7SHbcG9dbrwUUg54,34347569
4
+ blocksolver/_blqmr.cp39-win_amd64.dll.a,sha256=Y7ej3xoapseI1xUDbNJncO7n9CMYuollIx0UvFlw624,1696
5
+ blocksolver/__init__.py,sha256=aJUyjo4lOmok718swroWNLPFctuyfGzxdmPBJnpu_00,1982
6
+ blocksolver/blqmr.py,sha256=kpkl32V8bWRGKtc8UOLoAor2yFzLryYcH_6zq02KpHo,41042
7
+ blocksolver-0.8.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: meson
3
+ Root-Is-Purelib: false
4
+ Tag: cp39-cp39-win_amd64