structsolve 0.4.0__tar.gz → 0.4.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.
- {structsolve-0.4.0/structsolve.egg-info → structsolve-0.4.1}/PKG-INFO +5 -5
- {structsolve-0.4.0 → structsolve-0.4.1}/README.md +4 -4
- {structsolve-0.4.0 → structsolve-0.4.1}/pyproject.toml +1 -1
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/linear_buckling.py +47 -16
- {structsolve-0.4.0 → structsolve-0.4.1/structsolve.egg-info}/PKG-INFO +5 -5
- {structsolve-0.4.0 → structsolve-0.4.1}/tests/test_linear_buckling.py +40 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/LICENSE +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/setup.cfg +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/__init__.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/analysis.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/arc_length.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/arc_length_crisfield.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/arc_length_riks.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/freq.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/logger.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/newton_raphson.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/sparseutils.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve/static.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve.egg-info/SOURCES.txt +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve.egg-info/dependency_links.txt +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve.egg-info/requires.txt +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/structsolve.egg-info/top_level.txt +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/tests/test_analysis.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/tests/test_arc_length.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/tests/test_freq.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/tests/test_newton_raphson.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/tests/test_sparseutils.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.1}/tests/test_static.py +0 -0
- {structsolve-0.4.0 → structsolve-0.4.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.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Structural analysis solvers
|
|
5
5
|
Author-email: "Saullo G. P. Castro" <castrosaullo@gmail.com>
|
|
6
6
|
License: BSD-2-Clause
|
|
@@ -41,8 +41,7 @@ Github Actions status:
|
|
|
41
41
|
|
|
42
42
|
Coverage status:
|
|
43
43
|
[](https://github.com/saullocastro/structsolve/actions/workflows/coverage.yml)
|
|
44
|
-
[](https://codecov.io/gh/saullocastro/structsolve)
|
|
46
45
|
|
|
47
46
|
Structural analysis solvers tailored for semi-analytical models
|
|
48
47
|
===============================================================
|
|
@@ -61,7 +60,7 @@ Currently these solvers are pretty much compatible with my other repositories
|
|
|
61
60
|
Citing this library
|
|
62
61
|
===================
|
|
63
62
|
|
|
64
|
-
Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.4.
|
|
63
|
+
Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.4.1). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
|
|
65
64
|
|
|
66
65
|
|
|
67
66
|
Documentation
|
|
@@ -76,7 +75,8 @@ History
|
|
|
76
75
|
|
|
77
76
|
See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
|
|
78
77
|
|
|
79
|
-
* version 0.4.
|
|
78
|
+
* version 0.4.1 (2026-09-17)
|
|
79
|
+
- Fixed the eigenvalue shift of the sparse solver of `lb`, which could return buckling loads higher than the critical ones
|
|
80
80
|
- Newton-Raphson with full Newton iterations and a relative convergence
|
|
81
81
|
criterion by default, reaching quadratic convergence with exact tangent
|
|
82
82
|
stiffness matrices
|
|
@@ -4,8 +4,7 @@ Github Actions status:
|
|
|
4
4
|
|
|
5
5
|
Coverage status:
|
|
6
6
|
[](https://github.com/saullocastro/structsolve/actions/workflows/coverage.yml)
|
|
7
|
-
[](https://codecov.io/gh/saullocastro/structsolve)
|
|
9
8
|
|
|
10
9
|
Structural analysis solvers tailored for semi-analytical models
|
|
11
10
|
===============================================================
|
|
@@ -24,7 +23,7 @@ Currently these solvers are pretty much compatible with my other repositories
|
|
|
24
23
|
Citing this library
|
|
25
24
|
===================
|
|
26
25
|
|
|
27
|
-
Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.4.
|
|
26
|
+
Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.4.1). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
|
|
28
27
|
|
|
29
28
|
|
|
30
29
|
Documentation
|
|
@@ -39,7 +38,8 @@ History
|
|
|
39
38
|
|
|
40
39
|
See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
|
|
41
40
|
|
|
42
|
-
* version 0.4.
|
|
41
|
+
* version 0.4.1 (2026-09-17)
|
|
42
|
+
- Fixed the eigenvalue shift of the sparse solver of `lb`, which could return buckling loads higher than the critical ones
|
|
43
43
|
- Newton-Raphson with full Newton iterations and a relative convergence
|
|
44
44
|
criterion by default, reaching quadratic convergence with exact tangent
|
|
45
45
|
stiffness matrices
|
|
@@ -1,29 +1,60 @@
|
|
|
1
1
|
import warnings
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
|
-
from scipy.sparse
|
|
4
|
+
from scipy.sparse import csc_matrix
|
|
5
|
+
from scipy.sparse.linalg import eigsh, splu
|
|
5
6
|
from scipy.linalg import eigh
|
|
6
7
|
|
|
7
8
|
from .logger import msg, warn
|
|
8
9
|
from .sparseutils import remove_null_cols
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
def _estimate_sigma(K, KG):
|
|
12
|
+
def _estimate_sigma(K, KG, safety=10., max_iter=50, rel_tol=1e-3):
|
|
13
|
+
r"""Shift of the Cayley mode used by :func:`lb`
|
|
14
|
+
|
|
15
|
+
With ``sigma > 0``, ``eigsh(A=KG, M=K, sigma=sigma, mode='cayley',
|
|
16
|
+
which='SM')`` returns the eigenvalues `\mu` of ``KG u = mu K u`` with the
|
|
17
|
+
smallest `|(\mu + \sigma)/(\mu - \sigma)|`. This ordering selects the most
|
|
18
|
+
negative `\mu`, i.e. the lowest positive load multipliers `-1/\mu`, only
|
|
19
|
+
when `\sigma` is larger than `|\mu|` of these critical eigenvalues.
|
|
20
|
+
Otherwise the eigenvalues closest to `-\sigma` are returned.
|
|
21
|
+
|
|
22
|
+
The largest `|\mu|` is estimated with power iterations on
|
|
23
|
+
`[K]^{-1}[K_G]`, whose norm ratio in the `[K]`-norm increases towards the
|
|
24
|
+
largest `|\mu|`, and multiplied by ``safety``. The default shift ``1.`` is
|
|
25
|
+
returned when ``K`` is singular, not positive definite, or the linear
|
|
26
|
+
solution is inaccurate.
|
|
27
|
+
|
|
28
|
+
"""
|
|
12
29
|
try:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
with warnings.catch_warnings():
|
|
31
|
+
warnings.simplefilter("ignore")
|
|
32
|
+
lu = splu(csc_matrix(K))
|
|
33
|
+
x = np.random.RandomState(42).randn(K.shape[0])
|
|
34
|
+
Kx = K @ x
|
|
35
|
+
mu_max = 0.
|
|
36
|
+
for i in range(max_iter):
|
|
37
|
+
xKx = x @ Kx
|
|
38
|
+
if not np.isfinite(xKx) or xKx <= 0:
|
|
39
|
+
return 1.
|
|
40
|
+
x = x / np.sqrt(xKx)
|
|
41
|
+
rhs = KG @ x
|
|
42
|
+
y = lu.solve(rhs)
|
|
43
|
+
Ky = K @ y
|
|
44
|
+
if i == 0:
|
|
45
|
+
residual = np.linalg.norm(Ky - rhs)
|
|
46
|
+
if not residual <= 1e-6 * np.linalg.norm(rhs):
|
|
47
|
+
return 1.
|
|
48
|
+
# ||y||_K / ||x||_K, with ||x||_K = 1
|
|
49
|
+
ratio = np.sqrt(abs(y @ Ky))
|
|
50
|
+
if not np.isfinite(ratio) or ratio == 0:
|
|
51
|
+
return 1.
|
|
52
|
+
converged = i > 0 and ratio - mu_max <= rel_tol * ratio
|
|
53
|
+
mu_max = max(mu_max, ratio)
|
|
54
|
+
if converged:
|
|
55
|
+
break
|
|
56
|
+
x, Kx = y, Ky
|
|
57
|
+
return safety * mu_max
|
|
27
58
|
except Exception:
|
|
28
59
|
return 1.
|
|
29
60
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: structsolve
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Structural analysis solvers
|
|
5
5
|
Author-email: "Saullo G. P. Castro" <castrosaullo@gmail.com>
|
|
6
6
|
License: BSD-2-Clause
|
|
@@ -41,8 +41,7 @@ Github Actions status:
|
|
|
41
41
|
|
|
42
42
|
Coverage status:
|
|
43
43
|
[](https://github.com/saullocastro/structsolve/actions/workflows/coverage.yml)
|
|
44
|
-
[](https://codecov.io/gh/saullocastro/structsolve)
|
|
46
45
|
|
|
47
46
|
Structural analysis solvers tailored for semi-analytical models
|
|
48
47
|
===============================================================
|
|
@@ -61,7 +60,7 @@ Currently these solvers are pretty much compatible with my other repositories
|
|
|
61
60
|
Citing this library
|
|
62
61
|
===================
|
|
63
62
|
|
|
64
|
-
Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.4.
|
|
63
|
+
Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.4.1). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
|
|
65
64
|
|
|
66
65
|
|
|
67
66
|
Documentation
|
|
@@ -76,7 +75,8 @@ History
|
|
|
76
75
|
|
|
77
76
|
See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
|
|
78
77
|
|
|
79
|
-
* version 0.4.
|
|
78
|
+
* version 0.4.1 (2026-09-17)
|
|
79
|
+
- Fixed the eigenvalue shift of the sparse solver of `lb`, which could return buckling loads higher than the critical ones
|
|
80
80
|
- Newton-Raphson with full Newton iterations and a relative convergence
|
|
81
81
|
criterion by default, reaching quadratic convergence with exact tangent
|
|
82
82
|
stiffness matrices
|
|
@@ -41,6 +41,46 @@ def test_lb_dense_solver():
|
|
|
41
41
|
np.testing.assert_allclose(eigvals[:5], -2.0, rtol=1e-6)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
def test_lb_sparse_shift_mixed_spectrum():
|
|
45
|
+
"""Sparse and dense lb agree when the load multipliers have mixed signs
|
|
46
|
+
|
|
47
|
+
Regression test: the shift of the sparse solver was a single Rayleigh
|
|
48
|
+
quotient, in which the positive and negative eigenvalues of
|
|
49
|
+
``KG u = mu K u`` cancel. The shift landed below the critical ``|mu|``
|
|
50
|
+
and eigsh returned the load multipliers near ``1/sigma`` instead of the
|
|
51
|
+
lowest ones.
|
|
52
|
+
"""
|
|
53
|
+
from scipy.sparse import diags
|
|
54
|
+
from structsolve.linear_buckling import _estimate_sigma
|
|
55
|
+
|
|
56
|
+
n = 80
|
|
57
|
+
k = np.linspace(1e6, 5e6, n)
|
|
58
|
+
lambdas = np.concatenate([[1.0, 1.0, 1.1, 1.2],
|
|
59
|
+
np.linspace(1.5, 4., 36),
|
|
60
|
+
-np.linspace(1.5, 4., 40)])
|
|
61
|
+
mu = -1. / lambdas
|
|
62
|
+
K = diags(k).tocsc()
|
|
63
|
+
KG = diags(mu * k).tocsc()
|
|
64
|
+
|
|
65
|
+
# the shift must bound the largest |mu| of the critical eigenvalues
|
|
66
|
+
assert _estimate_sigma(K, KG) >= np.abs(mu).max()
|
|
67
|
+
|
|
68
|
+
eig_sparse, _ = lb(K, KG, silent=True, num_eigvalues=10)
|
|
69
|
+
eig_dense, _ = lb(K, KG, silent=True, sparse_solver=False)
|
|
70
|
+
np.testing.assert_allclose(eig_sparse[:4], [1.0, 1.0, 1.1, 1.2],
|
|
71
|
+
rtol=1e-8)
|
|
72
|
+
np.testing.assert_allclose(eig_sparse[:4], eig_dense[:4], rtol=1e-8)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_lb_sparse_singular_K():
|
|
76
|
+
"""The shift falls back to 1 when K is singular"""
|
|
77
|
+
from structsolve.linear_buckling import _estimate_sigma
|
|
78
|
+
|
|
79
|
+
K = csc_matrix(np.diag([1., 2., 0., 4., 5.]))
|
|
80
|
+
KG = csc_matrix(np.eye(5))
|
|
81
|
+
assert _estimate_sigma(K, KG) == 1.
|
|
82
|
+
|
|
83
|
+
|
|
44
84
|
def test_lb_plate_buckling_fsdt():
|
|
45
85
|
"""Test plate buckling (FSDT) based on semi-analytical Ritz method.
|
|
46
86
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|