structsolve 0.6.0__tar.gz → 0.6.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.
Files changed (36) hide show
  1. {structsolve-0.6.0/structsolve.egg-info → structsolve-0.6.1}/PKG-INFO +6 -4
  2. {structsolve-0.6.0 → structsolve-0.6.1}/README.md +4 -3
  3. {structsolve-0.6.0 → structsolve-0.6.1}/pyproject.toml +2 -1
  4. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/arpackutils.py +36 -4
  5. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/linear_buckling.py +4 -3
  6. {structsolve-0.6.0 → structsolve-0.6.1/structsolve.egg-info}/PKG-INFO +6 -4
  7. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_linear_buckling_unsymmetric.py +3 -0
  8. {structsolve-0.6.0 → structsolve-0.6.1}/LICENSE +0 -0
  9. {structsolve-0.6.0 → structsolve-0.6.1}/setup.cfg +0 -0
  10. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/__init__.py +0 -0
  11. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/analysis.py +0 -0
  12. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/arc_length.py +0 -0
  13. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/arc_length_crisfield.py +0 -0
  14. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/arc_length_riks.py +0 -0
  15. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/callbacks.py +0 -0
  16. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/freq.py +0 -0
  17. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/logger.py +0 -0
  18. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/newton_raphson.py +0 -0
  19. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/sparseutils.py +0 -0
  20. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve/static.py +0 -0
  21. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve.egg-info/SOURCES.txt +0 -0
  22. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve.egg-info/dependency_links.txt +0 -0
  23. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve.egg-info/requires.txt +0 -0
  24. {structsolve-0.6.0 → structsolve-0.6.1}/structsolve.egg-info/top_level.txt +0 -0
  25. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_analysis.py +0 -0
  26. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_arc_length.py +0 -0
  27. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_arpackutils.py +0 -0
  28. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_follower_freq_static.py +0 -0
  29. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_follower_loads.py +0 -0
  30. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_freq.py +0 -0
  31. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_linear_buckling.py +0 -0
  32. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_newton_raphson.py +0 -0
  33. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_sparse_first.py +0 -0
  34. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_sparseutils.py +0 -0
  35. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_static.py +0 -0
  36. {structsolve-0.6.0 → structsolve-0.6.1}/tests/test_static_deflection.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structsolve
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: Structural analysis solvers
5
5
  Author-email: "Saullo G. P. Castro" <castrosaullo@gmail.com>
6
6
  License: BSD-2-Clause
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.13
21
21
  Classifier: Programming Language :: Python :: 3.14
22
22
  Classifier: Operating System :: Microsoft :: Windows
23
23
  Classifier: Operating System :: Unix
24
+ Classifier: Environment :: WebAssembly :: Emscripten
24
25
  Requires-Python: >=3.8
25
26
  Description-Content-Type: text/markdown
26
27
  License-File: LICENSE
@@ -62,7 +63,7 @@ Currently these solvers are pretty much compatible with my other repositories
62
63
  Citing this library
63
64
  ===================
64
65
 
65
- Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.6.0). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
66
+ Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.6.1). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
66
67
 
67
68
 
68
69
  Documentation
@@ -77,9 +78,10 @@ History
77
78
 
78
79
  See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
79
80
 
80
- * version 0.6.0 (2026-10-08)
81
+ * version 0.6.1 (2026-10-08)
82
+ - Pyodide support: `await micropip.install("structsolve")` in the browser, and the whole test suite runs in Pyodide in GitHub Actions
81
83
  - `lb` and `freq` always run the sparse solvers first, whatever the size of the problem, with verified results; the dense solvers are only a last resort within `max_dense_size`, with a `DenseFallbackWarning`
82
- - ARPACK's `ncv` is capped at 32 when SciPy is linked against the Intel MKL versions whose `dsteqr` is faulty (new `structsolve.arpackutils`)
84
+ - ARPACK's `ncv` is capped at 32 when SciPy is linked against the Intel MKL versions whose `dsteqr` is faulty (new `structsolve.arpackutils`), computing more than 15 eigenpairs in passes whose eigenvectors are made orthonormal with a Rayleigh-Ritz projection
83
85
  - Unsymmetric `lb`: a shift search finds the lowest positive real load multiplier, instead of silently returning negative or complex ones
84
86
  - The test extra no longer requires `buckling` and `composites`
85
87
  * version 0.5.3 (2026-10-06)
@@ -27,7 +27,7 @@ Currently these solvers are pretty much compatible with my other repositories
27
27
  Citing this library
28
28
  ===================
29
29
 
30
- Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.6.0). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
30
+ Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.6.1). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
31
31
 
32
32
 
33
33
  Documentation
@@ -42,9 +42,10 @@ History
42
42
 
43
43
  See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
44
44
 
45
- * version 0.6.0 (2026-10-08)
45
+ * version 0.6.1 (2026-10-08)
46
+ - Pyodide support: `await micropip.install("structsolve")` in the browser, and the whole test suite runs in Pyodide in GitHub Actions
46
47
  - `lb` and `freq` always run the sparse solvers first, whatever the size of the problem, with verified results; the dense solvers are only a last resort within `max_dense_size`, with a `DenseFallbackWarning`
47
- - ARPACK's `ncv` is capped at 32 when SciPy is linked against the Intel MKL versions whose `dsteqr` is faulty (new `structsolve.arpackutils`)
48
+ - ARPACK's `ncv` is capped at 32 when SciPy is linked against the Intel MKL versions whose `dsteqr` is faulty (new `structsolve.arpackutils`), computing more than 15 eigenpairs in passes whose eigenvectors are made orthonormal with a Rayleigh-Ritz projection
48
49
  - Unsymmetric `lb`: a shift search finds the lowest positive real load multiplier, instead of silently returning negative or complex ones
49
50
  - The test extra no longer requires `buckling` and `composites`
50
51
  * version 0.5.3 (2026-10-06)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "structsolve"
7
- version = "0.6.0"
7
+ version = "0.6.1"
8
8
  description = "Structural analysis solvers"
9
9
  readme = "README.md"
10
10
  license = {text = "BSD-2-Clause"}
@@ -31,6 +31,7 @@ classifiers = [
31
31
  "Programming Language :: Python :: 3.14",
32
32
  "Operating System :: Microsoft :: Windows",
33
33
  "Operating System :: Unix",
34
+ "Environment :: WebAssembly :: Emscripten",
34
35
  ]
35
36
  dependencies = [
36
37
  "numpy",
@@ -11,7 +11,9 @@ MKL 2025.0.1 or newer is not affected, neither are the non-symmetric drivers
11
11
  of :func:`scipy.sparse.linalg.eigs`, which do not call ``dsteqr``.
12
12
 
13
13
  :func:`capped_eigsh` keeps ``ncv <= 32`` when :func:`arpack_max_ncv` says so,
14
- computing more than 15 eigenpairs in several calls with deflation.
14
+ computing more than 15 eigenpairs in several calls with deflation, whose
15
+ eigenvectors are combined with a Rayleigh-Ritz projection such that they
16
+ are orthonormal also across the calls.
15
17
 
16
18
  The cap is decided by :func:`arpack_max_ncv` and can be overridden with
17
19
  the module attribute :data:`ARPACK_MAX_NCV` or the environment variable
@@ -32,6 +34,7 @@ import sys
32
34
  import warnings
33
35
 
34
36
  import numpy as np
37
+ from scipy.linalg import cholesky, eigh, solve_triangular
35
38
  from scipy.sparse import csc_matrix
36
39
  from scipy.sparse.linalg import LinearOperator, splu
37
40
  from scipy.sparse.linalg import eigsh as _scipy_eigsh
@@ -281,6 +284,34 @@ def _deflation_shift(w, far_shift):
281
284
  return 0.5*(last[i] + last[i + 1])
282
285
 
283
286
 
287
+ def _rayleigh_ritz(A, M, V):
288
+ r"""Rayleigh-Ritz projection of `[A]\{x\} = w [M]\{x\}` onto `[V]`
289
+
290
+ The eigenvectors of different passes of :func:`capped_eigsh` are only
291
+ `[M]`-orthogonal to the accuracy of ARPACK, e.g. `10^{-6}` between
292
+ close eigenvalues of different passes. `[V]` is `[M]`-orthonormalized
293
+ with the Cholesky factor `[L]` of `[V]^T[M][V]`, and the projected
294
+ problem `[W]^T[A][W]\{y\} = w\{y\}`, with `[W] = [V][L]^{-T}`, is
295
+ solved with the LAPACK driver ``dsyevr`` (``driver='evr'``), which does
296
+ not use the ``dsteqr`` of Intel MKL broken above 32 x 32 matrices, see
297
+ :func:`dsteqr_is_faulty`. The returned eigenvectors `[W]\{y\}` are
298
+ `[M]`-orthonormal to the rounding errors, and the Ritz values are at
299
+ least as accurate as the eigenvalues of the passes.
300
+
301
+ Returns
302
+ -------
303
+ w, x : ndarray
304
+ The Ritz values by increasing value and the Ritz vectors.
305
+
306
+ """
307
+ MV = M @ V
308
+ L = cholesky(0.5*(V.T @ MV + MV.T @ V), lower=True)
309
+ W = solve_triangular(L, V.T, lower=True).T
310
+ H = W.T @ (A @ W)
311
+ w, Y = eigh(0.5*(H + H.T), driver='evr')
312
+ return w, W @ Y
313
+
314
+
284
315
  def capped_eigsh(A, k, M, sigma, which, mode='normal', tol=0):
285
316
  r""":func:`scipy.sparse.linalg.eigsh` with ``ncv`` from :func:`arpack_ncv`
286
317
 
@@ -312,7 +343,9 @@ def capped_eigsh(A, k, M, sigma, which, mode='normal', tol=0):
312
343
  in the study of the panels cylinders it was 30 to 45% faster and gave
313
344
  eigenvalues 5 to 10 times more accurate. Each pass factorizes
314
345
  `[A] - \sigma_d [M]` with SuperLU, and every call starts from
315
- :func:`start_vector`.
346
+ :func:`start_vector`. The eigenvectors of all the passes are finally
347
+ combined with a Rayleigh-Ritz projection, see :func:`_rayleigh_ritz`,
348
+ such that they are `[M]`-orthonormal also across the passes.
316
349
 
317
350
  Returns
318
351
  -------
@@ -359,5 +392,4 @@ def capped_eigsh(A, k, M, sigma, which, mode='normal', tol=0):
359
392
  w = np.concatenate((w, wi))
360
393
  V = np.hstack((V, Vi))
361
394
  release_memory()
362
- order = np.argsort(w, kind='stable')
363
- return w[order], V[:, order]
395
+ return _rayleigh_ritz(A, M, V)
@@ -862,9 +862,10 @@ def lb(K, KG, tol=0, sparse_solver=True, silent=False,
862
862
  MKL versions returns wrong eigenvectors for matrices larger than
863
863
  32 x 32, which ARPACK uses with the size ``ncv``. When such a LAPACK is
864
864
  detected, ``ncv`` is capped at 32 and more than 15 eigenpairs are
865
- computed in several passes, see :mod:`structsolve.arpackutils`, where
866
- the cap can be overridden, e.g. with the environment variable
867
- ``STRUCTSOLVE_ARPACK_MAX_NCV=0`` to lift it with MKL 2025.0.1 or newer.
865
+ computed in several passes, combined with a Rayleigh-Ritz projection,
866
+ see :mod:`structsolve.arpackutils`, where the cap can be overridden,
867
+ e.g. with the environment variable ``STRUCTSOLVE_ARPACK_MAX_NCV=0`` to
868
+ lift it with MKL 2025.0.1 or newer.
868
869
  The non-symmetric drivers of :func:`scipy.sparse.linalg.eigs` are not
869
870
  affected.
870
871
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structsolve
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: Structural analysis solvers
5
5
  Author-email: "Saullo G. P. Castro" <castrosaullo@gmail.com>
6
6
  License: BSD-2-Clause
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.13
21
21
  Classifier: Programming Language :: Python :: 3.14
22
22
  Classifier: Operating System :: Microsoft :: Windows
23
23
  Classifier: Operating System :: Unix
24
+ Classifier: Environment :: WebAssembly :: Emscripten
24
25
  Requires-Python: >=3.8
25
26
  Description-Content-Type: text/markdown
26
27
  License-File: LICENSE
@@ -62,7 +63,7 @@ Currently these solvers are pretty much compatible with my other repositories
62
63
  Citing this library
63
64
  ===================
64
65
 
65
- Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.6.0). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
66
+ Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.6.1). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
66
67
 
67
68
 
68
69
  Documentation
@@ -77,9 +78,10 @@ History
77
78
 
78
79
  See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
79
80
 
80
- * version 0.6.0 (2026-10-08)
81
+ * version 0.6.1 (2026-10-08)
82
+ - Pyodide support: `await micropip.install("structsolve")` in the browser, and the whole test suite runs in Pyodide in GitHub Actions
81
83
  - `lb` and `freq` always run the sparse solvers first, whatever the size of the problem, with verified results; the dense solvers are only a last resort within `max_dense_size`, with a `DenseFallbackWarning`
82
- - ARPACK's `ncv` is capped at 32 when SciPy is linked against the Intel MKL versions whose `dsteqr` is faulty (new `structsolve.arpackutils`)
84
+ - ARPACK's `ncv` is capped at 32 when SciPy is linked against the Intel MKL versions whose `dsteqr` is faulty (new `structsolve.arpackutils`), computing more than 15 eigenpairs in passes whose eigenvectors are made orthonormal with a Rayleigh-Ritz projection
83
85
  - Unsymmetric `lb`: a shift search finds the lowest positive real load multiplier, instead of silently returning negative or complex ones
84
86
  - The test extra no longer requires `buckling` and `composites`
85
87
  * version 0.5.3 (2026-10-06)
@@ -217,6 +217,9 @@ def test_lb_nearly_symmetric(sparse_solver, max_dense_size):
217
217
  assert np.all(relative_residuals(Kn, KG, eigvals, eigvecs) < 1e-8)
218
218
 
219
219
 
220
+ @pytest.mark.skipif(sys.platform == 'emscripten',
221
+ reason='no subprocesses in Pyodide, whose SciPy is not '
222
+ 'linked to MKL')
220
223
  def test_eig_complex_mkl_crash_regression():
221
224
  """Regression test: with Intel MKL 2025.0.0, scipy.linalg.eig on these
222
225
  real 48 x 48 matrices (LAPACK dggev) corrupts the heap and the process
File without changes
File without changes