structsolve 0.9.1__tar.gz → 0.9.2__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 (39) hide show
  1. {structsolve-0.9.1/structsolve.egg-info → structsolve-0.9.2}/PKG-INFO +5 -5
  2. {structsolve-0.9.1 → structsolve-0.9.2}/README.md +4 -4
  3. {structsolve-0.9.1 → structsolve-0.9.2}/pyproject.toml +1 -1
  4. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/arc_length.py +24 -2
  5. {structsolve-0.9.1 → structsolve-0.9.2/structsolve.egg-info}/PKG-INFO +5 -5
  6. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_arc_length.py +27 -0
  7. {structsolve-0.9.1 → structsolve-0.9.2}/LICENSE +0 -0
  8. {structsolve-0.9.1 → structsolve-0.9.2}/setup.cfg +0 -0
  9. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/__init__.py +0 -0
  10. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/analysis.py +0 -0
  11. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/arc_length_crisfield.py +0 -0
  12. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/arc_length_riks.py +0 -0
  13. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/arpackutils.py +0 -0
  14. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/callbacks.py +0 -0
  15. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/convergence.py +0 -0
  16. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/freq.py +0 -0
  17. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/linear_buckling.py +0 -0
  18. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/logger.py +0 -0
  19. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/newton_raphson.py +0 -0
  20. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/sparseutils.py +0 -0
  21. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve/static.py +0 -0
  22. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve.egg-info/SOURCES.txt +0 -0
  23. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve.egg-info/dependency_links.txt +0 -0
  24. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve.egg-info/requires.txt +0 -0
  25. {structsolve-0.9.1 → structsolve-0.9.2}/structsolve.egg-info/top_level.txt +0 -0
  26. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_analysis.py +0 -0
  27. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_arpackutils.py +0 -0
  28. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_follower_freq_static.py +0 -0
  29. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_follower_loads.py +0 -0
  30. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_freq.py +0 -0
  31. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_linear_buckling.py +0 -0
  32. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_linear_buckling_unsymmetric.py +0 -0
  33. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_load_factor_dependent_load.py +0 -0
  34. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_newton_raphson.py +0 -0
  35. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_reuse.py +0 -0
  36. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_sparse_first.py +0 -0
  37. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_sparseutils.py +0 -0
  38. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_static.py +0 -0
  39. {structsolve-0.9.1 → structsolve-0.9.2}/tests/test_static_deflection.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structsolve
3
- Version: 0.9.1
3
+ Version: 0.9.2
4
4
  Summary: Structural analysis solvers
5
5
  Author-email: "Saullo G. P. Castro" <castrosaullo@gmail.com>
6
6
  License-Expression: BSD-3-Clause
@@ -63,7 +63,7 @@ Currently these solvers are pretty much compatible with my other repository
63
63
  Citing this library
64
64
  ===================
65
65
 
66
- Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.9.1). 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.9.2). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
67
67
 
68
68
 
69
69
  Documentation
@@ -78,12 +78,12 @@ History
78
78
 
79
79
  See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
80
80
 
81
- * version 0.9.1 (2026-10-24)
82
- - documentation published again: pandoc installed in the documentation workflow
83
- * version 0.9.0 (2026-10-24)
81
+ * version 0.9.2 (2026-10-24), including 0.9.0 and 0.9.1
84
82
  - Crisfield's convergence criterion is the default of the non-linear analyses, `Analysis.convergence = 'crisfield'`, with `relTOL = 1e-9`: the residual and the reference forces are measured with the norm scaled by the diagonal of `calc_kC()` over the free degrees of freedom; the former check is kept with `convergence = 'relative'`
85
83
  - `lb` returns the negative load multipliers closest to zero after the positive ones, and a tensile reference load no longer needs the dense fallback
86
84
  - `freq(sort=True)` sorts and filters `lambda2` together with the eigenvectors, and rigid-body modes no longer fail the verification of the residuals
85
+ - arc-length solvers: a converged step that points back along the path is repeated with half the arc length, instead of being accepted
86
+ - documentation published again: pandoc installed in the documentation workflow
87
87
  * version 0.8.0 (2026-10-14)
88
88
  - Fewer evaluations and factorizations, same solutions: `dR/dlbd` is evaluated together with the tangent stiffness matrix only, Newton-Raphson reuses the factorization of the tangent while it is not updated, the follower linear static analysis factorizes `K0` once, and `lb` estimates its shift and the inertia of `K` once for all its attempts
89
89
  * version 0.7.0 (2026-10-13)
@@ -28,7 +28,7 @@ Currently these solvers are pretty much compatible with my other repository
28
28
  Citing this library
29
29
  ===================
30
30
 
31
- Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.9.1). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
31
+ Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.9.2). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
32
32
 
33
33
 
34
34
  Documentation
@@ -43,12 +43,12 @@ History
43
43
 
44
44
  See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
45
45
 
46
- * version 0.9.1 (2026-10-24)
47
- - documentation published again: pandoc installed in the documentation workflow
48
- * version 0.9.0 (2026-10-24)
46
+ * version 0.9.2 (2026-10-24), including 0.9.0 and 0.9.1
49
47
  - Crisfield's convergence criterion is the default of the non-linear analyses, `Analysis.convergence = 'crisfield'`, with `relTOL = 1e-9`: the residual and the reference forces are measured with the norm scaled by the diagonal of `calc_kC()` over the free degrees of freedom; the former check is kept with `convergence = 'relative'`
50
48
  - `lb` returns the negative load multipliers closest to zero after the positive ones, and a tensile reference load no longer needs the dense fallback
51
49
  - `freq(sort=True)` sorts and filters `lambda2` together with the eigenvectors, and rigid-body modes no longer fail the verification of the residuals
50
+ - arc-length solvers: a converged step that points back along the path is repeated with half the arc length, instead of being accepted
51
+ - documentation published again: pandoc installed in the documentation workflow
52
52
  * version 0.8.0 (2026-10-14)
53
53
  - Fewer evaluations and factorizations, same solutions: `dR/dlbd` is evaluated together with the tangent stiffness matrix only, Newton-Raphson reuses the factorization of the tangent while it is not updated, the follower linear static analysis factorizes `K0` once, and `lb` estimates its shift and the inertia of `K` once for all its attempts
54
54
  * version 0.7.0 (2026-10-13)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "structsolve"
7
- version = "0.9.1"
7
+ version = "0.9.2"
8
8
  description = "Structural analysis solvers"
9
9
  readme = "README.md"
10
10
  license = "BSD-3-Clause"
@@ -174,8 +174,20 @@ def _solver_arc_length(an, method, silent=False):
174
174
  angle, since both have the length `\Delta s`.
175
175
 
176
176
  The step fails when `\delta\lambda` cannot be computed or is not
177
- finite. With full Newton-Raphson, `[K_T]` is updated at every iteration
178
- at the current iterate `(c + \Delta c, \lambda + \Delta\lambda)`; with
177
+ finite, and when the converged increment points against the tangent
178
+ predictor `(\Delta c_{pred}, \Delta\lambda_{pred})` of the step,
179
+ `\langle (\Delta c, \Delta\lambda), (\Delta c_{pred},
180
+ \Delta\lambda_{pred}) \rangle \le 0`. The previous converged point is
181
+ also at the distance `\Delta s` from the last one, and with long steps
182
+ or near a limit point the iterations may converge to it and then trace
183
+ the path backwards, the "doubling back" that [2]_ (p. 56) avoids with
184
+ the choice of the root. The accepted points are thus on the side of the
185
+ tangent predictor of the hyperplane normal to it, in the inner product
186
+ above, through the last converged point, as the points of the plane of
187
+ Riks [1]_, normal to the tangent at the distance `\Delta s` from the
188
+ last converged point. With full Newton-Raphson, `[K_T]` is updated at
189
+ every iteration at the current iterate `(c + \Delta c, \lambda +
190
+ \Delta\lambda)`; with
179
191
  ``an.modified_NR = True`` the factorization at the last converged state
180
192
  is used for the first ``an.compute_every_n`` iterations and the tangent
181
193
  is then updated every ``an.compute_every_n`` iterations; at the first
@@ -313,6 +325,9 @@ def _solver_arc_length(an, method, silent=False):
313
325
  sign = 1.
314
326
  dlbd = sign*arc_length/norm_q
315
327
  dc = dlbd*dc_q_conv
328
+ # tangent predictor, the forward direction of the step
329
+ dc_pred = dc
330
+ dlbd_pred = dlbd
316
331
 
317
332
  msg('Step %d, lbd %1.5f, arc-length increment %1.5f' % (step_num, lbd, arc_length),
318
333
  level=1, silent=silent)
@@ -393,6 +408,13 @@ def _solver_arc_length(an, method, silent=False):
393
408
  dc = dc + dc_R + varlbd*dc_q
394
409
  dlbd = dlbd + varlbd
395
410
 
411
+ if converged and inner(dc, dlbd, dc_pred, dlbd_pred) <= 0:
412
+ # the increment points backwards, e.g. to the previous converged
413
+ # point, which is also at the distance arc_length
414
+ warn('Diverged - the step returned along the path already traced',
415
+ level=2, silent=silent)
416
+ converged = False
417
+
396
418
  finished = False
397
419
  if converged and lbd + dlbd > 1. and lbd < 1.:
398
420
  msg('Load factor 1.0 exceeded, correcting to load factor 1.0...', level=1, silent=silent)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structsolve
3
- Version: 0.9.1
3
+ Version: 0.9.2
4
4
  Summary: Structural analysis solvers
5
5
  Author-email: "Saullo G. P. Castro" <castrosaullo@gmail.com>
6
6
  License-Expression: BSD-3-Clause
@@ -63,7 +63,7 @@ Currently these solvers are pretty much compatible with my other repository
63
63
  Citing this library
64
64
  ===================
65
65
 
66
- Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.9.1). 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.9.2). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
67
67
 
68
68
 
69
69
  Documentation
@@ -78,12 +78,12 @@ History
78
78
 
79
79
  See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
80
80
 
81
- * version 0.9.1 (2026-10-24)
82
- - documentation published again: pandoc installed in the documentation workflow
83
- * version 0.9.0 (2026-10-24)
81
+ * version 0.9.2 (2026-10-24), including 0.9.0 and 0.9.1
84
82
  - Crisfield's convergence criterion is the default of the non-linear analyses, `Analysis.convergence = 'crisfield'`, with `relTOL = 1e-9`: the residual and the reference forces are measured with the norm scaled by the diagonal of `calc_kC()` over the free degrees of freedom; the former check is kept with `convergence = 'relative'`
85
83
  - `lb` returns the negative load multipliers closest to zero after the positive ones, and a tensile reference load no longer needs the dense fallback
86
84
  - `freq(sort=True)` sorts and filters `lambda2` together with the eigenvectors, and rigid-body modes no longer fail the verification of the residuals
85
+ - arc-length solvers: a converged step that points back along the path is repeated with half the arc length, instead of being accepted
86
+ - documentation published again: pandoc installed in the documentation workflow
87
87
  * version 0.8.0 (2026-10-14)
88
88
  - Fewer evaluations and factorizations, same solutions: `dR/dlbd` is evaluated together with the tangent stiffness matrix only, Newton-Raphson reuses the factorization of the tangent while it is not updated, the follower linear static analysis factorizes `K0` once, and `lb` estimates its shift and the inertia of `K` once for all its attempts
89
89
  * version 0.7.0 (2026-10-13)
@@ -139,6 +139,33 @@ def test_arc_length_snap_back(method, convergence, relTOL):
139
139
  assert cs[-1, 0] > 2.
140
140
 
141
141
 
142
+ @pytest.mark.parametrize('convergence, relTOL', [('relative', 1.e-6),
143
+ ('crisfield', 1.e-9)])
144
+ @pytest.mark.parametrize('method', METHODS)
145
+ def test_arc_length_no_doubling_back(method, convergence, relTOL):
146
+ """Long steps through the limit point at 10 times the limit load
147
+
148
+ The previous converged point is at the distance of the arc length from
149
+ the last one, and the iterations of the second step may converge to it,
150
+ which would trace the path backwards, the load factor decreasing below
151
+ zero without ever reaching 1.0. Such a step points against the tangent
152
+ predictor, and it is repeated with a shorter arc length.
153
+
154
+ """
155
+ p = von_mises_truss(frac=10., ks=1.)
156
+ p.analysis(NL_method=method, initialInc=0.2, convergence=convergence,
157
+ relTOL=relTOL)
158
+ p.an.static(NLgeom=True, silent=True)
159
+ check_equilibrium(p)
160
+ inc = np.asarray(p.an.increments)
161
+ cs = np.asarray(p.an.cs)
162
+ assert inc[-1] == 1.0
163
+ assert np.all(np.diff(np.r_[0., cs[:, 0]]) > 0)
164
+ np.testing.assert_allclose(cs[-1],
165
+ p.solve_reference(c0=cs[-1], tol=1e-12),
166
+ rtol=1e-6)
167
+
168
+
142
169
  @pytest.mark.parametrize('method', METHODS)
143
170
  def test_arc_length_step_cutting(method):
144
171
  p = von_mises_truss(frac=1.5)
File without changes
File without changes