structsolve 0.3.0__tar.gz → 0.4.0__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 (38) hide show
  1. {structsolve-0.3.0/structsolve.egg-info → structsolve-0.4.0}/PKG-INFO +44 -2
  2. structsolve-0.4.0/README.md +70 -0
  3. {structsolve-0.3.0 → structsolve-0.4.0}/pyproject.toml +2 -1
  4. structsolve-0.4.0/structsolve/__init__.py +24 -0
  5. structsolve-0.4.0/structsolve/analysis.py +243 -0
  6. structsolve-0.4.0/structsolve/arc_length.py +304 -0
  7. structsolve-0.4.0/structsolve/arc_length_crisfield.py +17 -0
  8. structsolve-0.4.0/structsolve/arc_length_riks.py +17 -0
  9. structsolve-0.4.0/structsolve/freq.py +169 -0
  10. structsolve-0.4.0/structsolve/linear_buckling.py +132 -0
  11. structsolve-0.4.0/structsolve/logger.py +72 -0
  12. structsolve-0.4.0/structsolve/newton_raphson.py +332 -0
  13. {structsolve-0.3.0 → structsolve-0.4.0}/structsolve/sparseutils.py +20 -4
  14. {structsolve-0.3.0 → structsolve-0.4.0}/structsolve/static.py +26 -15
  15. {structsolve-0.3.0 → structsolve-0.4.0/structsolve.egg-info}/PKG-INFO +44 -2
  16. {structsolve-0.3.0 → structsolve-0.4.0}/structsolve.egg-info/SOURCES.txt +3 -0
  17. structsolve-0.4.0/tests/test_arc_length.py +191 -0
  18. structsolve-0.4.0/tests/test_newton_raphson.py +149 -0
  19. structsolve-0.3.0/README.md +0 -29
  20. structsolve-0.3.0/structsolve/__init__.py +0 -23
  21. structsolve-0.3.0/structsolve/analysis.py +0 -170
  22. structsolve-0.3.0/structsolve/arc_length_crisfield.py +0 -166
  23. structsolve-0.3.0/structsolve/arc_length_riks.py +0 -138
  24. structsolve-0.3.0/structsolve/freq.py +0 -136
  25. structsolve-0.3.0/structsolve/linear_buckling.py +0 -106
  26. structsolve-0.3.0/structsolve/logger.py +0 -16
  27. structsolve-0.3.0/structsolve/newton_raphson.py +0 -169
  28. {structsolve-0.3.0 → structsolve-0.4.0}/LICENSE +0 -0
  29. {structsolve-0.3.0 → structsolve-0.4.0}/setup.cfg +0 -0
  30. {structsolve-0.3.0 → structsolve-0.4.0}/structsolve.egg-info/dependency_links.txt +0 -0
  31. {structsolve-0.3.0 → structsolve-0.4.0}/structsolve.egg-info/requires.txt +0 -0
  32. {structsolve-0.3.0 → structsolve-0.4.0}/structsolve.egg-info/top_level.txt +0 -0
  33. {structsolve-0.3.0 → structsolve-0.4.0}/tests/test_analysis.py +0 -0
  34. {structsolve-0.3.0 → structsolve-0.4.0}/tests/test_freq.py +0 -0
  35. {structsolve-0.3.0 → structsolve-0.4.0}/tests/test_linear_buckling.py +0 -0
  36. {structsolve-0.3.0 → structsolve-0.4.0}/tests/test_sparseutils.py +0 -0
  37. {structsolve-0.3.0 → structsolve-0.4.0}/tests/test_static.py +0 -0
  38. {structsolve-0.3.0 → structsolve-0.4.0}/tests/test_static_deflection.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structsolve
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Structural analysis solvers
5
5
  Author-email: "Saullo G. P. Castro" <castrosaullo@gmail.com>
6
6
  License: BSD-2-Clause
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
21
22
  Classifier: Operating System :: Microsoft :: Windows
22
23
  Classifier: Operating System :: Unix
23
24
  Requires-Python: >=3.8
@@ -57,9 +58,50 @@ Currently these solvers are pretty much compatible with my other repositories
57
58
  [buckling](https://github.com/saullocastro/buckling).
58
59
 
59
60
 
61
+ Citing this library
62
+ ===================
63
+
64
+ Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.4.0). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
65
+
66
+
67
+ Documentation
68
+ =============
69
+
70
+ The documentation is available on: https://saullocastro.github.io/structsolve.
71
+
72
+
73
+
74
+ History
75
+ =======
76
+
77
+ See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
78
+
79
+ * version 0.4.0 (2026-09-17)
80
+ - Newton-Raphson with full Newton iterations and a relative convergence
81
+ criterion by default, reaching quadratic convergence with exact tangent
82
+ stiffness matrices
83
+ - Fixed the load-factor bookkeeping of Newton-Raphson, which could finish
84
+ before reaching the full load
85
+ - Arc-length methods (Riks and Crisfield) rewritten, able to trace limit
86
+ points, snap-through and snap-back until a load factor of exactly 1.0
87
+ - Sphinx documentation
88
+ * version 0.3.1 (2026-04-09)
89
+ - Robust estimation of the eigenvalue shift for singular matrices in
90
+ `freq` and `lb`, and new `skip_null_cols` argument
91
+ - Python 3.14 support
92
+ - Estimation of the eigenvalue shift in `freq` and `lb`
93
+ - Packaging with `pyproject.toml`, GitHub Actions and a test suite
94
+ * version 0.2.2 (2019-03-02)
95
+ - Release of 0.2.1 with an updated distribution
96
+ - Fixed the dense solver of `freq`
97
+ - `freq` returns the eigenvalues `lambda**2` instead of the natural
98
+ frequencies
99
+ * version 0.1.0 (2018-06-23)
100
+ - First release, with the solvers from `compmech`
101
+
60
102
  License
61
103
  -------
62
- Distrubuted in the 3-Clause BSD license (https://raw.github.com/saullocastro/structsolve/master/LICENSE).
104
+ Distributed in the 3-Clause BSD license (https://raw.github.com/saullocastro/structsolve/master/LICENSE).
63
105
 
64
106
  Contact: S.G.P.Castro@tudelft.nl
65
107
 
@@ -0,0 +1,70 @@
1
+ Github Actions status:
2
+ [![pytest](https://github.com/saullocastro/structsolve/actions/workflows/pytest.yml/badge.svg)](https://github.com/saullocastro/structsolve/actions/workflows/pytest.yml)
3
+ [![Deploy](https://github.com/saullocastro/structsolve/actions/workflows/pythonpublish.yml/badge.svg)](https://github.com/saullocastro/structsolve/actions/workflows/pythonpublish.yml)
4
+
5
+ Coverage status:
6
+ [![codecov](https://github.com/saullocastro/structsolve/actions/workflows/coverage.yml/badge.svg)](https://github.com/saullocastro/structsolve/actions/workflows/coverage.yml)
7
+ [![Codecov Status](https://codecov.io/gh/saullocastro/structsolve/branch/master/graph/badge.svg)](https://codecov.io/gh/saullocastro/structsolve)
8
+
9
+
10
+ Structural analysis solvers tailored for semi-analytical models
11
+ ===============================================================
12
+
13
+ - Linear statics: [K]{u} = {f}
14
+ - Eigensolver for Linear buckling: ([K] + lambda[KG]){u} = 0
15
+ - Eigensolver for dynamics: ([K] + lambda^2[M]){u} = 0
16
+ - Nonlinear statics using Newton-Raphson
17
+ - Nonlinear statics using the Arc-Length method
18
+
19
+ Currently these solvers are pretty much compatible with my other repositories
20
+ [panels](https://github.com/saullocastro/panels),
21
+ [buckling](https://github.com/saullocastro/buckling).
22
+
23
+
24
+ Citing this library
25
+ ===================
26
+
27
+ Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.4.0). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
28
+
29
+
30
+ Documentation
31
+ =============
32
+
33
+ The documentation is available on: https://saullocastro.github.io/structsolve.
34
+
35
+
36
+
37
+ History
38
+ =======
39
+
40
+ See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
41
+
42
+ * version 0.4.0 (2026-09-17)
43
+ - Newton-Raphson with full Newton iterations and a relative convergence
44
+ criterion by default, reaching quadratic convergence with exact tangent
45
+ stiffness matrices
46
+ - Fixed the load-factor bookkeeping of Newton-Raphson, which could finish
47
+ before reaching the full load
48
+ - Arc-length methods (Riks and Crisfield) rewritten, able to trace limit
49
+ points, snap-through and snap-back until a load factor of exactly 1.0
50
+ - Sphinx documentation
51
+ * version 0.3.1 (2026-04-09)
52
+ - Robust estimation of the eigenvalue shift for singular matrices in
53
+ `freq` and `lb`, and new `skip_null_cols` argument
54
+ - Python 3.14 support
55
+ - Estimation of the eigenvalue shift in `freq` and `lb`
56
+ - Packaging with `pyproject.toml`, GitHub Actions and a test suite
57
+ * version 0.2.2 (2019-03-02)
58
+ - Release of 0.2.1 with an updated distribution
59
+ - Fixed the dense solver of `freq`
60
+ - `freq` returns the eigenvalues `lambda**2` instead of the natural
61
+ frequencies
62
+ * version 0.1.0 (2018-06-23)
63
+ - First release, with the solvers from `compmech`
64
+
65
+ License
66
+ -------
67
+ Distributed in the 3-Clause BSD license (https://raw.github.com/saullocastro/structsolve/master/LICENSE).
68
+
69
+ Contact: S.G.P.Castro@tudelft.nl
70
+
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "structsolve"
7
- version = "0.3.0"
7
+ version = "0.4.0"
8
8
  description = "Structural analysis solvers"
9
9
  readme = "README.md"
10
10
  license = {text = "BSD-2-Clause"}
@@ -28,6 +28,7 @@ classifiers = [
28
28
  "Programming Language :: Python :: 3.11",
29
29
  "Programming Language :: Python :: 3.12",
30
30
  "Programming Language :: Python :: 3.13",
31
+ "Programming Language :: Python :: 3.14",
31
32
  "Operating System :: Microsoft :: Windows",
32
33
  "Operating System :: Unix",
33
34
  ]
@@ -0,0 +1,24 @@
1
+ r"""
2
+ ===============================================
3
+ Structural Analysis Solver (:mod:`structsolve`)
4
+ ===============================================
5
+
6
+ .. currentmodule:: structsolve
7
+
8
+ Structural analysis solvers tailored for semi-analytical models, available
9
+ directly from the ``structsolve`` namespace:
10
+
11
+ - :class:`.Analysis`: linear and non-linear static analyses, using the
12
+ Newton-Raphson or the arc-length methods
13
+ - :func:`.solve`: solution of linear systems removing null rows and columns
14
+ - :func:`.static`: linear static analysis
15
+ - :func:`.lb`: linear buckling analysis
16
+ - :func:`.freq`: frequency analysis
17
+
18
+ """
19
+ from __future__ import absolute_import
20
+
21
+ from .analysis import Analysis
22
+ from .freq import freq
23
+ from .linear_buckling import lb
24
+ from .static import solve, static
@@ -0,0 +1,243 @@
1
+ from __future__ import absolute_import
2
+
3
+ from .static import solve
4
+ from .logger import msg
5
+ from .newton_raphson import _solver_NR
6
+ from .arc_length_riks import _solver_arc_length_riks
7
+ from .arc_length_crisfield import _solver_arc_length_crisfield
8
+
9
+
10
+ class Analysis(object):
11
+ r"""Class that embodies all data required for linear/non-linear analysis
12
+
13
+ The structural model is defined by the callables passed to the
14
+ constructor, which return the force vectors and stiffness matrices. The
15
+ static analysis, linear or non-linear, is run with :meth:`.static`, whose
16
+ solution is stored in the attributes ``increments`` and ``cs``.
17
+
18
+ For non-linear analyses, the internal force vector
19
+ `\{F_{int}(c)\}` must be in equilibrium with the external force
20
+ vector scaled by the load factor `\lambda`:
21
+
22
+ .. math::
23
+
24
+ \{R\} = \lambda \{F_{ext}\} - \{F_{int}(c)\} = \{0\}
25
+
26
+ and the tangent stiffness matrix `[K_T] = [K_C] + [K_G]`, given by the
27
+ callables ``calc_kC`` and ``calc_kG``, should be the exact derivative of
28
+ `\{F_{int}\}` with respect to `\{c\}`, such that the Newton-Raphson
29
+ iterations converge quadratically.
30
+
31
+ The analysis parameters are attributes of this class, described in the
32
+ following tables together with their default values:
33
+
34
+ ======================== ==================================================
35
+ Non-Linear Algorithm Description
36
+ ======================== ==================================================
37
+ ``NL_method`` ``str``, ``'NR'`` (default) for the
38
+ Newton-Raphson method, see
39
+ :func:`.newton_raphson._solver_NR`, or
40
+ ``'arc_length_riks'`` and
41
+ ``'arc_length_crisfield'`` for the arc-length
42
+ methods, see
43
+ :func:`.arc_length._solver_arc_length`
44
+ ``line_search`` ``bool``, activates a safeguarding line-search,
45
+ for the Newton-Raphson method only. The full
46
+ step is tried first and only reduced when it
47
+ fails a sufficient-decrease test on the
48
+ residual norm. Default is ``False``
49
+ ``max_iter_line_search`` ``int``, maximum number of iterations of the
50
+ line-search. Default is ``20``
51
+ ``modified_NR`` ``bool``, activates the modified Newton-Raphson
52
+ method, where the tangent stiffness matrix is
53
+ not updated at every iteration. Default is
54
+ ``False``, i.e. full Newton-Raphson
55
+ ``compute_every_n`` ``int``, if ``modified_NR=True``, the tangent
56
+ stiffness matrix is updated at every `n`
57
+ iterations. Default is ``6``
58
+ ``kT_initial_state`` ``bool``, if ``modified_NR=True``, tells if the
59
+ tangent stiffness matrix should be calculated
60
+ already at the first iteration of the analysis,
61
+ which is required for example when initial
62
+ imperfections take place. Otherwise the linear
63
+ constitutive stiffness matrix is used. Default
64
+ is ``True``
65
+ ======================== ==================================================
66
+
67
+ ================ =================================================
68
+ Incrementation Description
69
+ ================ =================================================
70
+ ``initialInc`` initial load increment. In the arc-length
71
+ methods it defines the initial arc-length
72
+ increment, corresponding to a load factor
73
+ increment of ``initialInc`` along the initial
74
+ tangent. Default is ``0.1``
75
+ ``minInc`` minimum increment; the analysis stops when the
76
+ load increment (Newton-Raphson) or the arc-length
77
+ increment (arc-length methods) becomes smaller
78
+ than ``minInc``. Default is ``1.e-4``
79
+ ``maxInc`` maximum load increment, or maximum arc-length
80
+ increment for the arc-length methods. Default is
81
+ ``1.``
82
+ ``maxArcLength`` maximum cumulative arc length covered by the
83
+ arc-length methods. The arc length is
84
+ dimensionless, with displacements scaled by the
85
+ linear solution for a load factor of 1, such
86
+ that in the linear regime an arc length of
87
+ about ``sqrt(2)`` corresponds to a load factor
88
+ increment of 1. Default is ``18``
89
+ ================ =================================================
90
+
91
+ ==================== ============================================
92
+ Convergence Criteria Description
93
+ ==================== ============================================
94
+ ``relTOL`` the convergence is achieved when the norm of
95
+ the residual force vector is smaller than
96
+ ``relTOL`` times the largest norm between the
97
+ external and internal force vectors. Not used
98
+ if ``None``. Default is ``1.e-6``
99
+ ``absTOL`` the convergence is also achieved when the
100
+ maximum absolute residual force is smaller
101
+ than this value, which depends on the units of
102
+ the model. Not used if ``None``. Default is
103
+ ``None``
104
+ ``maxNumIter`` maximum number of iterations (corrections) of a
105
+ step; if achieved the increment is reduced.
106
+ Default is ``30``
107
+ ``too_slow_TOL`` a step is considered too slow when the smallest
108
+ residual norm is not reduced by this fraction
109
+ over the last iterations; the increment is then
110
+ reduced. Default is ``0.005``
111
+ ==================== ============================================
112
+
113
+ Parameters
114
+ ----------
115
+ calc_fext : callable, optional
116
+ ``calc_fext(inc=1., silent=False)``, must return a 1-D array with the
117
+ external force vector. Required for linear and non-linear static
118
+ analyses. The non-linear solvers call it with ``inc=1.`` and scale the
119
+ returned vector by the load factor.
120
+ calc_fint : callable, optional
121
+ ``calc_fint(c, silent=False)``, must return a 1-D array with the
122
+ internal force vector for the solution vector ``c``. Required for
123
+ non-linear analyses.
124
+ calc_kC : callable, optional
125
+ ``calc_kC(c=None, NLgeom=False, silent=False)``, must return a sparse
126
+ matrix with the constitutive stiffness matrix. With ``c=None`` and
127
+ ``NLgeom=False`` it must return the linear stiffness matrix, and with
128
+ ``NLgeom=True`` the constitutive part of the tangent stiffness matrix
129
+ at ``c``. Required for linear and non-linear static analyses.
130
+ calc_kG : callable, optional
131
+ ``calc_kG(c=None, NLgeom=False, silent=False)``, must return a sparse
132
+ matrix with the geometric stiffness matrix at ``c``. It is called
133
+ with ``NLgeom=True``. Required for non-linear analyses.
134
+
135
+ Attributes
136
+ ----------
137
+ increments : list
138
+ Load factors of the converged increments, filled by :meth:`.static`.
139
+ cs : list
140
+ Solution vectors of the converged increments, filled by
141
+ :meth:`.static`.
142
+ last_analysis : str
143
+ Type of the last analysis run, ``'static'`` after :meth:`.static`.
144
+
145
+ """
146
+ __slots__ = ['NL_method', 'line_search', 'max_iter_line_search',
147
+ 'modified_NR', 'compute_every_n',
148
+ 'kT_initial_state', 'initialInc', 'minInc', 'maxInc',
149
+ 'maxArcLength', 'absTOL', 'relTOL', 'maxNumIter', 'too_slow_TOL',
150
+ 'increments', 'cs', 'last_analysis', 'calc_fext', 'calc_kC',
151
+ 'calc_fint', 'calc_kG']
152
+
153
+
154
+ def __init__(self, calc_fext=None, calc_fint=None, calc_kC=None,
155
+ calc_kG=None):
156
+ # non-linear algorithm
157
+ self.NL_method = 'NR'
158
+ self.line_search = False
159
+ self.max_iter_line_search = 20
160
+ self.modified_NR = False
161
+ self.compute_every_n = 6
162
+ self.kT_initial_state = True
163
+ # incrementation
164
+ self.initialInc = 0.1
165
+ self.minInc = 1.e-4
166
+ self.maxInc = 1.
167
+ self.maxArcLength = 18
168
+ # convergence criteria
169
+ self.absTOL = None
170
+ self.relTOL = 1.e-6
171
+ self.maxNumIter = 30
172
+ self.too_slow_TOL = 0.005
173
+
174
+ # required methods
175
+ self.calc_fext = calc_fext
176
+ self.calc_fint = calc_fint
177
+ self.calc_kC = calc_kC
178
+ self.calc_kG = calc_kG
179
+
180
+ # outputs to be filled
181
+ self.increments = None
182
+ self.cs = None
183
+
184
+ # flag telling the last analysis
185
+ self.last_analysis = ''
186
+
187
+
188
+ def static(self, NLgeom=False, silent=False):
189
+ r"""General solver for static analyses
190
+
191
+ The linear analysis solves `[K_C]\{c\} = \{F_{ext}\}` using
192
+ :func:`.solve`. The non-linear analysis uses the solver selected by
193
+ the ``NL_method`` attribute.
194
+
195
+ Parameters
196
+ ----------
197
+ NLgeom : bool, optional
198
+ Flag to indicate whether a linear or a non-linear analysis is to
199
+ be performed.
200
+ silent : bool, optional
201
+ A boolean to tell whether the log messages should be printed.
202
+
203
+ Returns
204
+ -------
205
+ increments : list
206
+ Load factors of the converged increments. A linear analysis
207
+ returns ``[1.]``. Non-linear analyses finish at a load factor of
208
+ exactly ``1.`` unless they are stopped earlier, see the
209
+ documentation of each solver.
210
+ cs : list
211
+ Solution vectors of the converged increments.
212
+
213
+ """
214
+ self.increments = []
215
+ self.cs = []
216
+
217
+ if NLgeom:
218
+ self.maxInc = max(self.initialInc, self.maxInc)
219
+ msg('Started Non-Linear Static Analysis', silent=silent)
220
+ if self.NL_method == 'NR':
221
+ _solver_NR(self, silent=silent)
222
+ elif self.NL_method == 'arc_length_riks':
223
+ _solver_arc_length_riks(self, silent=silent)
224
+ elif self.NL_method == 'arc_length_crisfield':
225
+ _solver_arc_length_crisfield(self, silent=silent)
226
+ else:
227
+ raise ValueError('{0} is an invalid NL_method'.format(self.NL_method))
228
+
229
+ else:
230
+ msg('Started Linear Static Analysis', silent=silent)
231
+ fext = self.calc_fext(silent=silent)
232
+ k0 = self.calc_kC(silent=silent)
233
+
234
+ c = solve(k0, fext, silent=silent)
235
+
236
+ self.cs.append(c)
237
+ self.increments.append(1.)
238
+ msg('Finished Linear Static Analysis', silent=silent)
239
+
240
+ self.last_analysis = 'static'
241
+
242
+ return self.increments, self.cs
243
+