structsolve 0.8.0__tar.gz → 0.9.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 (44) hide show
  1. {structsolve-0.8.0/structsolve.egg-info → structsolve-0.9.0}/PKG-INFO +13 -11
  2. {structsolve-0.8.0 → structsolve-0.9.0}/README.md +7 -4
  3. {structsolve-0.8.0 → structsolve-0.9.0}/pyproject.toml +8 -8
  4. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/analysis.py +145 -68
  5. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/arc_length.py +166 -38
  6. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/arc_length_crisfield.py +12 -0
  7. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/arc_length_riks.py +11 -0
  8. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/arpackutils.py +220 -38
  9. structsolve-0.9.0/structsolve/callbacks.py +278 -0
  10. structsolve-0.9.0/structsolve/convergence.py +345 -0
  11. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/freq.py +151 -76
  12. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/linear_buckling.py +723 -133
  13. structsolve-0.9.0/structsolve/logger.py +87 -0
  14. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/newton_raphson.py +254 -61
  15. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/sparseutils.py +61 -5
  16. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/static.py +31 -2
  17. {structsolve-0.8.0 → structsolve-0.9.0/structsolve.egg-info}/PKG-INFO +13 -11
  18. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve.egg-info/SOURCES.txt +1 -0
  19. structsolve-0.9.0/tests/test_analysis.py +147 -0
  20. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_arc_length.py +89 -2
  21. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_arpackutils.py +47 -0
  22. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_follower_freq_static.py +8 -10
  23. structsolve-0.9.0/tests/test_freq.py +298 -0
  24. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_linear_buckling.py +194 -1
  25. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_linear_buckling_unsymmetric.py +161 -10
  26. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_load_factor_dependent_load.py +8 -6
  27. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_newton_raphson.py +113 -0
  28. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_sparseutils.py +41 -0
  29. structsolve-0.9.0/tests/test_static.py +129 -0
  30. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_static_deflection.py +1 -4
  31. structsolve-0.8.0/structsolve/callbacks.py +0 -160
  32. structsolve-0.8.0/structsolve/logger.py +0 -72
  33. structsolve-0.8.0/tests/test_analysis.py +0 -73
  34. structsolve-0.8.0/tests/test_freq.py +0 -88
  35. structsolve-0.8.0/tests/test_static.py +0 -63
  36. {structsolve-0.8.0 → structsolve-0.9.0}/LICENSE +0 -0
  37. {structsolve-0.8.0 → structsolve-0.9.0}/setup.cfg +0 -0
  38. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve/__init__.py +0 -0
  39. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve.egg-info/dependency_links.txt +0 -0
  40. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve.egg-info/requires.txt +0 -0
  41. {structsolve-0.8.0 → structsolve-0.9.0}/structsolve.egg-info/top_level.txt +0 -0
  42. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_follower_loads.py +0 -0
  43. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_reuse.py +0 -0
  44. {structsolve-0.8.0 → structsolve-0.9.0}/tests/test_sparse_first.py +0 -0
@@ -1,19 +1,18 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structsolve
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Structural analysis solvers
5
5
  Author-email: "Saullo G. P. Castro" <castrosaullo@gmail.com>
6
- License: BSD-2-Clause
7
- Project-URL: Homepage, https://github.com/compmech/structsolve
8
- Project-URL: Repository, https://github.com/compmech/structsolve
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/saullocastro/structsolve
8
+ Project-URL: Documentation, https://saullocastro.github.io/structsolve/
9
+ Project-URL: Repository, https://github.com/saullocastro/structsolve
9
10
  Keywords: structural analysis,stress,vibration,linear buckling,newton raphson,arc length
10
11
  Classifier: Development Status :: 4 - Beta
11
12
  Classifier: Intended Audience :: Science/Research
12
13
  Classifier: Intended Audience :: Developers
13
14
  Classifier: Intended Audience :: Education
14
15
  Classifier: Topic :: Scientific/Engineering :: Mathematics
15
- Classifier: License :: OSI Approved :: BSD License
16
- Classifier: Programming Language :: Python :: 3.9
17
16
  Classifier: Programming Language :: Python :: 3.10
18
17
  Classifier: Programming Language :: Python :: 3.11
19
18
  Classifier: Programming Language :: Python :: 3.12
@@ -22,7 +21,7 @@ Classifier: Programming Language :: Python :: 3.14
22
21
  Classifier: Operating System :: Microsoft :: Windows
23
22
  Classifier: Operating System :: Unix
24
23
  Classifier: Environment :: WebAssembly :: Emscripten
25
- Requires-Python: >=3.8
24
+ Requires-Python: >=3.10
26
25
  Description-Content-Type: text/markdown
27
26
  License-File: LICENSE
28
27
  Requires-Dist: numpy
@@ -57,15 +56,14 @@ Structural analysis solvers tailored for semi-analytical models
57
56
  - Load vectors that depend on the load factor, e.g. prescribed displacements
58
57
  imposed exactly as linear constraints
59
58
 
60
- Currently these solvers are pretty much compatible with my other repositories
61
- [panels](https://github.com/saullocastro/panels),
62
- [buckling](https://github.com/saullocastro/buckling).
59
+ Currently these solvers are pretty much compatible with my other repository
60
+ [panels](https://github.com/saullocastro/panels).
63
61
 
64
62
 
65
63
  Citing this library
66
64
  ===================
67
65
 
68
- Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.8.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.9.0). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
69
67
 
70
68
 
71
69
  Documentation
@@ -80,6 +78,10 @@ History
80
78
 
81
79
  See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
82
80
 
81
+ * version 0.9.0 (2026-10-24)
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'`
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
84
+ - `freq(sort=True)` sorts and filters `lambda2` together with the eigenvectors, and rigid-body modes no longer fail the verification of the residuals
83
85
  * version 0.8.0 (2026-10-14)
84
86
  - 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
85
87
  * version 0.7.0 (2026-10-13)
@@ -21,15 +21,14 @@ Structural analysis solvers tailored for semi-analytical models
21
21
  - Load vectors that depend on the load factor, e.g. prescribed displacements
22
22
  imposed exactly as linear constraints
23
23
 
24
- Currently these solvers are pretty much compatible with my other repositories
25
- [panels](https://github.com/saullocastro/panels),
26
- [buckling](https://github.com/saullocastro/buckling).
24
+ Currently these solvers are pretty much compatible with my other repository
25
+ [panels](https://github.com/saullocastro/panels).
27
26
 
28
27
 
29
28
  Citing this library
30
29
  ===================
31
30
 
32
- Saullo G. P. Castro (2026). Structural analysis solvers tailored for semi-analytical models (Version 0.8.0). 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.0). Zenodo. DOI: https://doi.org/10.5281/zenodo.2581212.
33
32
 
34
33
 
35
34
  Documentation
@@ -44,6 +43,10 @@ History
44
43
 
45
44
  See [CHANGELOG.md](CHANGELOG.md) for the details of each version.
46
45
 
46
+ * version 0.9.0 (2026-10-24)
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'`
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
49
+ - `freq(sort=True)` sorts and filters `lambda2` together with the eigenvectors, and rigid-body modes no longer fail the verification of the residuals
47
50
  * version 0.8.0 (2026-10-14)
48
51
  - 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
49
52
  * version 0.7.0 (2026-10-13)
@@ -1,14 +1,15 @@
1
1
  [build-system]
2
- requires = ["setuptools>=64", "wheel"]
2
+ requires = ["setuptools>=77"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "structsolve"
7
- version = "0.8.0"
7
+ version = "0.9.0"
8
8
  description = "Structural analysis solvers"
9
9
  readme = "README.md"
10
- license = {text = "BSD-2-Clause"}
11
- requires-python = ">=3.8"
10
+ license = "BSD-3-Clause"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.10"
12
13
  authors = [
13
14
  { name = "Saullo G. P. Castro", email = "castrosaullo@gmail.com" },
14
15
  ]
@@ -22,8 +23,6 @@ classifiers = [
22
23
  "Intended Audience :: Developers",
23
24
  "Intended Audience :: Education",
24
25
  "Topic :: Scientific/Engineering :: Mathematics",
25
- "License :: OSI Approved :: BSD License",
26
- "Programming Language :: Python :: 3.9",
27
26
  "Programming Language :: Python :: 3.10",
28
27
  "Programming Language :: Python :: 3.11",
29
28
  "Programming Language :: Python :: 3.12",
@@ -47,8 +46,9 @@ test = [
47
46
  ]
48
47
 
49
48
  [project.urls]
50
- Homepage = "https://github.com/compmech/structsolve"
51
- Repository = "https://github.com/compmech/structsolve"
49
+ Homepage = "https://github.com/saullocastro/structsolve"
50
+ Documentation = "https://saullocastro.github.io/structsolve/"
51
+ Repository = "https://github.com/saullocastro/structsolve"
52
52
 
53
53
  [tool.setuptools.packages.find]
54
54
  include = ["structsolve*"]
@@ -1,3 +1,13 @@
1
+ """Static analyses of a model given by callables (:class:`Analysis`)
2
+
3
+ The class :class:`Analysis` receives the callables that compute the force
4
+ vectors and the stiffness matrices of a model and runs a linear static
5
+ analysis, or a non-linear static analysis with the Newton-Raphson solver of
6
+ :mod:`.newton_raphson` or the arc-length solvers of :mod:`.arc_length`. The
7
+ optional keyword arguments of the callables are described in
8
+ :mod:`.callbacks`.
9
+
10
+ """
1
11
  from __future__ import absolute_import
2
12
 
3
13
  import numpy as np
@@ -5,7 +15,7 @@ import numpy as np
5
15
  from .static import solve, _factorize
6
16
  from .logger import msg, warn
7
17
  from . import callbacks
8
- from .newton_raphson import _check_convergence
18
+ from .newton_raphson import _check_convergence, _weights
9
19
  from .newton_raphson import _solver_NR
10
20
  from .arc_length_riks import _solver_arc_length_riks
11
21
  from .arc_length_crisfield import _solver_arc_length_crisfield
@@ -19,18 +29,11 @@ class Analysis(object):
19
29
  static analysis, linear or non-linear, is run with :meth:`.static`, whose
20
30
  solution is stored in the attributes ``increments`` and ``cs``.
21
31
 
22
- For non-linear analyses, the internal force vector
23
- `\{F_{int}(c)\}` must be in equilibrium with the external force
24
- vector scaled by the load factor `\lambda`:
25
-
26
- .. math::
27
-
28
- \{R\} = \lambda \{F_{ext}\} - \{F_{int}(c)\} = \{0\}
29
-
30
- and the tangent stiffness matrix `[K_T] = [K_C] + [K_G]`, given by the
31
- callables ``calc_kC`` and ``calc_kG``, should be the exact derivative of
32
- `\{F_{int}\}` with respect to `\{c\}`, such that the Newton-Raphson
33
- iterations converge quadratically.
32
+ The non-linear analyses find the solution vectors ``c`` for which the
33
+ internal force vector ``calc_fint(c)`` balances the external force
34
+ vector ``calc_fext(inc=1.)`` scaled by the load factor, using the
35
+ tangent stiffness matrix ``calc_kC(c, NLgeom=True) + calc_kG(c,
36
+ NLgeom=True)``.
34
37
 
35
38
  The analysis parameters are attributes of this class, described in the
36
39
  following tables together with their default values:
@@ -46,10 +49,9 @@ class Analysis(object):
46
49
  methods, see
47
50
  :func:`.arc_length._solver_arc_length`
48
51
  ``line_search`` ``bool``, activates a safeguarding line-search,
49
- for the Newton-Raphson method only. The full
50
- step is tried first and only reduced when it
51
- fails a sufficient-decrease test on the
52
- residual norm. Default is ``False``
52
+ for the Newton-Raphson method only, see
53
+ :func:`.newton_raphson._NR_iterations`. Default
54
+ is ``False``
53
55
  ``max_iter_line_search`` ``int``, maximum number of iterations of the
54
56
  line-search. Default is ``20``
55
57
  ``modified_NR`` ``bool``, activates the modified Newton-Raphson
@@ -84,22 +86,30 @@ class Analysis(object):
84
86
  increment for the arc-length methods. Default is
85
87
  ``1.``
86
88
  ``maxArcLength`` maximum cumulative arc length covered by the
87
- arc-length methods. The arc length is
88
- dimensionless, with displacements scaled by the
89
- linear solution for a load factor of 1, such
90
- that in the linear regime an arc length of
91
- about ``sqrt(2)`` corresponds to a load factor
92
- increment of 1. Default is ``18``
89
+ arc-length methods, dimensionless. Default is
90
+ ``18``
93
91
  ================ =================================================
94
92
 
95
93
  ==================== ============================================
96
94
  Convergence Criteria Description
97
95
  ==================== ============================================
98
- ``relTOL`` the convergence is achieved when the norm of
99
- the residual force vector is smaller than
100
- ``relTOL`` times the largest norm between the
101
- external and internal force vectors. Not used
102
- if ``None``. Default is ``1.e-6``
96
+ ``convergence`` ``str``, ``'crisfield'`` (default) for
97
+ Crisfield's criterion, the residual scaled
98
+ with the diagonal of the linear stiffness
99
+ matrix over the free degrees of freedom, or
100
+ ``'relative'`` for the Euclidean norm of the
101
+ residual, see :mod:`.convergence`
102
+ ``relTOL`` tolerance `\epsilon` of the relative force
103
+ imbalance: Crisfield's `\zeta \le` ``relTOL``,
104
+ or, with ``'relative'``, the norm of the
105
+ residual force vector smaller than ``relTOL``
106
+ times the largest norm between the external
107
+ and internal force vectors. Not used if
108
+ ``None``. Default is ``1.e-9``, the tight
109
+ tolerance of Crisfield's criterion with a
110
+ consistent tangent; until version 0.8.0 the
111
+ relative criterion was the only one, with the
112
+ default ``1.e-6``
103
113
  ``absTOL`` the convergence is also achieved when the
104
114
  maximum absolute residual force is smaller
105
115
  than this value, which depends on the units of
@@ -121,24 +131,75 @@ class Analysis(object):
121
131
  external force vector. Required for linear and non-linear static
122
132
  analyses. The non-linear solvers call it with ``inc=1.`` and scale the
123
133
  returned vector by the load factor. It may declare the optional
124
- keyword arguments ``c`` and ``lbd``, see the notes below.
134
+ keyword arguments ``c``, the current configuration, and ``lbd``, the
135
+ current load factor, and must then return the load vector of that
136
+ configuration and load factor for a unit load factor, ``inc=1.``,
137
+ see :mod:`.callbacks`. The linear static analysis never passes
138
+ ``lbd``.
125
139
  calc_fint : callable, optional
126
140
  ``calc_fint(c, silent=False)``, must return a 1-D array with the
127
141
  internal force vector for the solution vector ``c``. Required for
128
- non-linear analyses.
142
+ non-linear analyses. It may declare the optional keyword argument
143
+ ``inc``, which then receives the current load factor, see
144
+ :mod:`.callbacks`.
129
145
  calc_kC : callable, optional
130
146
  ``calc_kC(c=None, NLgeom=False, silent=False)``, must return a sparse
131
147
  matrix with the constitutive stiffness matrix. With ``c=None`` and
132
148
  ``NLgeom=False`` it must return the linear stiffness matrix, and with
133
149
  ``NLgeom=True`` the constitutive part of the tangent stiffness matrix
134
- at ``c``. Required for linear and non-linear static analyses.
150
+ at ``c``. Required for linear and non-linear static analyses. It may
151
+ declare the optional keyword argument ``inc``, which then receives
152
+ the current load factor in the calls with ``NLgeom=True``, see
153
+ :mod:`.callbacks`.
135
154
  calc_kG : callable, optional
136
155
  ``calc_kG(c=None, NLgeom=False, silent=False)``, must return a sparse
137
156
  matrix with the geometric stiffness matrix at ``c``. It is called
138
- with ``NLgeom=True``. Required for non-linear analyses.
157
+ with ``NLgeom=True``. Required for non-linear analyses. It may
158
+ declare the optional keyword argument ``inc``, which then receives
159
+ the current load factor, see :mod:`.callbacks`. The sum of
160
+ ``calc_kC`` and ``calc_kG`` may be unsymmetric.
161
+
162
+ Attributes
163
+ ----------
164
+ increments : list
165
+ Load factors of the converged increments, filled by :meth:`.static`.
166
+ cs : list
167
+ Solution vectors of the converged increments, filled by
168
+ :meth:`.static`.
169
+ last_analysis : str
170
+ Type of the last analysis run, ``'static'`` after :meth:`.static`.
139
171
 
140
172
  Notes
141
173
  -----
174
+ For non-linear analyses, the internal force vector
175
+ `\{F_{int}(c)\}` must be in equilibrium with the external force
176
+ vector scaled by the load factor `\lambda`:
177
+
178
+ .. math::
179
+
180
+ \{R\} = \lambda \{F_{ext}\} - \{F_{int}(c)\} = \{0\}
181
+
182
+ and the tangent stiffness matrix `[K_T] = [K_C] + [K_G]`, given by the
183
+ callables ``calc_kC`` and ``calc_kG``, should be the exact derivative of
184
+ `\{F_{int}\}` with respect to `\{c\}`, such that the Newton-Raphson
185
+ iterations converge quadratically. The convergence is checked by
186
+ default with Crisfield's criterion, the residual and the reference
187
+ force vectors scaled with the diagonal of the linear stiffness matrix
188
+ ``calc_kC()`` over the free degrees of freedom, such that it does not
189
+ depend on the units of each degree of freedom, e.g. translations and
190
+ rotations, see :mod:`.convergence`; ``convergence = 'relative'`` keeps
191
+ the Euclidean norm of the versions up to 0.8.0.
192
+
193
+ The line-search tries the full step first and only reduces it when it
194
+ fails a sufficient-decrease test on the norm of the residual of the
195
+ convergence criterion, see
196
+ :func:`.newton_raphson._NR_iterations`.
197
+
198
+ The arc length is dimensionless, with displacements scaled by the
199
+ linear solution for a load factor of 1, such that in the linear regime
200
+ an arc length of about ``sqrt(2)`` corresponds to a load factor
201
+ increment of 1, see :func:`.arc_length._solver_arc_length`.
202
+
142
203
  Configuration-dependent loads, e.g. follower pressures, are supported
143
204
  through optional keyword arguments, passed only to the callables that
144
205
  declare them explicitly, see :mod:`.callbacks`:
@@ -158,28 +219,19 @@ class Analysis(object):
158
219
  reference vector ``calc_fext(inc=1.)`` may be null. The solvers then
159
220
  use `\partial R/\partial \lambda` for the displacement scale of the
160
221
  arc-length methods, for the predictor of the first Newton-Raphson
161
- increment and as a reference of the relative convergence criterion,
162
- see :mod:`.callbacks`. The linear static analysis never passes
222
+ increment and as a reference of the convergence criterion, see
223
+ :mod:`.callbacks`. The linear static analysis never passes
163
224
  ``lbd``.
164
225
 
165
226
  The tangent stiffness matrix may then be unsymmetric, which the solvers
166
227
  support, since they use LU factorizations.
167
228
 
168
- Attributes
169
- ----------
170
- increments : list
171
- Load factors of the converged increments, filled by :meth:`.static`.
172
- cs : list
173
- Solution vectors of the converged increments, filled by
174
- :meth:`.static`.
175
- last_analysis : str
176
- Type of the last analysis run, ``'static'`` after :meth:`.static`.
177
-
178
229
  """
179
230
  __slots__ = ['NL_method', 'line_search', 'max_iter_line_search',
180
231
  'modified_NR', 'compute_every_n',
181
232
  'kT_initial_state', 'initialInc', 'minInc', 'maxInc',
182
- 'maxArcLength', 'absTOL', 'relTOL', 'maxNumIter', 'too_slow_TOL',
233
+ 'maxArcLength', 'convergence', 'absTOL', 'relTOL', 'maxNumIter',
234
+ 'too_slow_TOL',
183
235
  'increments', 'cs', 'last_analysis', 'calc_fext', 'calc_kC',
184
236
  'calc_fint', 'calc_kG']
185
237
 
@@ -199,8 +251,9 @@ class Analysis(object):
199
251
  self.maxInc = 1.
200
252
  self.maxArcLength = 18
201
253
  # convergence criteria
254
+ self.convergence = 'crisfield'
202
255
  self.absTOL = None
203
- self.relTOL = 1.e-6
256
+ self.relTOL = 1.e-9
204
257
  self.maxNumIter = 30
205
258
  self.too_slow_TOL = 0.005
206
259
 
@@ -221,28 +274,17 @@ class Analysis(object):
221
274
  def static(self, NLgeom=False, silent=False):
222
275
  r"""General solver for static analyses
223
276
 
224
- The linear analysis solves `[K_C]\{c\} = \{F_{ext}\}` using
277
+ The linear analysis solves the system of the linear stiffness matrix
278
+ ``calc_kC()`` and the external force vector ``calc_fext()`` using
225
279
  :func:`.solve`. When the load depends on the configuration, i.e.
226
280
  ``calc_fext`` declares the keyword argument ``c``, see
227
- :mod:`.callbacks`, the structure is still geometrically linear but
228
- the load is evaluated in the current configuration,
229
- `[K_C]\{c\} = \{F_{ext}(c)\}`, which is solved by the load
230
- correction iterations
231
-
232
- .. math::
233
-
234
- \{c_{k+1}\} = \{c_k\} + [K_C]^{-1}(\{F_{ext}(c_k)\}
235
- - [K_C]\{c_k\})
236
-
237
- starting from the solution of the reference load, until the relative
238
- criterion ``relTOL`` is satisfied, see
239
- :func:`.newton_raphson._check_convergence`, or ``maxNumIter``
240
- iterations are done. For a follower load whose force vector is
241
- affine in `c`, `\{F(c)\} = \{F_0\} - [K_f]\{c\}`, this is the
242
- solution of `([K_C] + [K_f])\{c\} = \{F_0\}`, with the
243
- convergence rate of the spectral radius of `[K_C]^{-1}[K_f]`, i.e.
244
- of the ratio of the load to the lowest critical load of the
245
- linearized problem; beyond it the iterations diverge. The non-linear
281
+ :mod:`.callbacks`, the load is evaluated in the current configuration
282
+ and corrected by iterations that reuse one factorization of the
283
+ linear stiffness matrix, starting from the solution of the reference
284
+ load, until the convergence criteria ``relTOL`` and ``absTOL`` are
285
+ satisfied, see :func:`.newton_raphson._check_convergence`, or
286
+ ``maxNumIter`` iterations are done; a warning is printed when they do
287
+ not converge and the last iterate is returned. The non-linear
246
288
  analysis uses the solver selected by the ``NL_method`` attribute.
247
289
 
248
290
  Parameters
@@ -263,6 +305,39 @@ class Analysis(object):
263
305
  cs : list
264
306
  Solution vectors of the converged increments.
265
307
 
308
+ Raises
309
+ ------
310
+ ValueError
311
+ When ``NLgeom=True`` and the ``NL_method`` attribute is not
312
+ ``'NR'``, ``'arc_length_riks'`` or ``'arc_length_crisfield'``.
313
+
314
+ Notes
315
+ -----
316
+ The linear analysis solves `[K_C]\{c\} = \{F_{ext}\}`. When the load
317
+ depends on the configuration, the structure is still geometrically
318
+ linear but the load is evaluated in the current configuration,
319
+ `[K_C]\{c\} = \{F_{ext}(c)\}`, which is solved by the load
320
+ correction iterations
321
+
322
+ .. math::
323
+
324
+ \{c_{k+1}\} = \{c_k\} + [K_C]^{-1}(\{F_{ext}(c_k)\}
325
+ - [K_C]\{c_k\})
326
+
327
+ starting from `\{c_0\} = [K_C]^{-1}\{F_{ext}\}`, the solution of the
328
+ reference load ``calc_fext()``, with `\{F_{ext}(c_k)\}` given by
329
+ ``calc_fext(inc=1., c=c_k)``. This is a fixed-point iteration
330
+ without the load stiffness in the iteration matrix. For a follower
331
+ load whose force vector is affine in `c`, `\{F(c)\} = \{F_0\} -
332
+ [K_f]\{c\}`, this is the solution of `([K_C] + [K_f])\{c\} =
333
+ \{F_0\}`, with the convergence rate of the spectral radius of
334
+ `[K_C]^{-1}[K_f]`, i.e. of the ratio of the load to the lowest
335
+ critical load of the linearized problem; beyond it the iterations
336
+ diverge. The error is multiplied by `-[K_C]^{-1}[K_f]` at each
337
+ iteration, whose spectral radius is `1/\min|\lambda|` over the load
338
+ multipliers `\lambda` of `([K_C] + \lambda [K_f])\{u\} = \{0\}`,
339
+ including the negative and complex ones.
340
+
266
341
  """
267
342
  self.increments = []
268
343
  self.cs = []
@@ -302,14 +377,16 @@ class Analysis(object):
302
377
  configuration-dependent load, see :meth:`.static`"""
303
378
  msg('Configuration-dependent load: load correction iterations',
304
379
  level=2, silent=silent)
380
+ w = _weights(self, k0)
305
381
  # k0 is factorized once for all the corrections
306
382
  solve_k0 = None
307
383
  for iteration in range(1, self.maxNumIter + 1):
308
384
  fext = self.calc_fext(inc=1., c=c, silent=True)
309
385
  fint = k0 @ c
310
386
  R = fext - fint
311
- conv, Rnorm, Rrel = _check_convergence(self, R, fint, fext)
312
- msg('Iteration: %d, relative ||R|| = %1.3e' % (iteration, Rrel),
387
+ conv, Rnorm, Rrel = _check_convergence(self, R, fint, fext, w=w)
388
+ msg('Iteration: %d, %s = %1.3e' % (iteration, 'zeta' if
389
+ self.convergence == 'crisfield' else 'relative ||R||', Rrel),
313
390
  level=3, silent=silent)
314
391
  if conv:
315
392
  return c