Skip to content

Commit 2177d3d

Browse files
Merge branch 'master' into joss
2 parents 2988506 + 02d9ece commit 2177d3d

File tree

9 files changed

+487
-415
lines changed

9 files changed

+487
-415
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
repository_url: https://test.pypi.org/legacy/
7171

7272
- name: Publish the release notes
73-
uses: release-drafter/release-drafter@v5.24.0
73+
uses: release-drafter/release-drafter@v5.25.0
7474
with:
7575
publish: ${{ steps.check-version.outputs.tag != '' }}
7676
tag: ${{ steps.check-version.outputs.tag }}

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ repos:
7373
rev: 1.7.0
7474
hooks:
7575
- id: nbqa-black
76-
additional_dependencies: [black==23.9.1]
76+
additional_dependencies: [black==23.10.0]
7777
- id: nbqa-pyupgrade
78-
additional_dependencies: [pyupgrade==3.14.0]
78+
additional_dependencies: [pyupgrade==3.15.0]
7979
args: ["--py39-plus"]
8080
- id: nbqa-isort
8181
additional_dependencies: [isort==5.12.0]

.readthedocs.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ python:
2323
extra_requirements:
2424
- dxf
2525
- rhino
26+
- numba

docs/installation.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ package index:
2626
2727
pip install sectionproperties
2828
29+
Installing ``Numba``
30+
--------------------
31+
32+
``Numba`` translates a subset of Python and NumPy code into fast machine code, allowing
33+
algorithms to approach the speeds of C. The speed of several ``sectionproperties``
34+
analysis functions have been enhanced with `numba <https://github.com/numba/numba>`_.
35+
To take advantage of this increase in performance you can install ``numba`` alongside
36+
``sectionproperties`` with:
37+
38+
.. code-block:: shell
39+
40+
pip install sectionproperties[numba]
2941
3042
Installing ``PARDISO`` Solver
3143
-----------------------------

noxfile.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,13 @@ def docs_build(session: Session) -> None:
212212
args.insert(0, "--color")
213213

214214
session.run_always(
215-
"poetry", "install", "--only", "main", "--extras", "dxf rhino", external=True
215+
"poetry",
216+
"install",
217+
"--only",
218+
"main",
219+
"--extras",
220+
"dxf rhino numba",
221+
external=True,
216222
)
217223
session.install(
218224
"furo",
@@ -243,7 +249,13 @@ def docs(session: Session) -> None:
243249
"""
244250
args = session.posargs or ["--open-browser", "docs", "docs/_build"]
245251
session.run_always(
246-
"poetry", "install", "--only", "main", "--extras", "dxf rhino", external=True
252+
"poetry",
253+
"install",
254+
"--only",
255+
"main",
256+
"--extras",
257+
"dxf rhino numba",
258+
external=True,
247259
)
248260
session.install(
249261
"furo",

poetry.lock

Lines changed: 381 additions & 376 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,22 @@ Changelog = "https://github.com/robbievanleeuwen/section-properties/releases"
4848

4949
[tool.poetry.dependencies]
5050
python = ">=3.9.0,<3.12"
51-
numpy = "^1.25.2" # numba requires numpy <1.26
52-
scipy = "^1.11.3"
51+
numpy = "^1.24.0"
52+
scipy = "^1.10.0"
5353
matplotlib = "^3.8.0"
54-
shapely = "^2.0.1"
54+
shapely = "^2.0.2"
5555
triangle = "^20230923"
56-
rich = "^13.6.0"
56+
rich = "^13.5.0"
5757
click = "^8.1.7"
58-
more-itertools = "^10.1.0"
59-
numba = "^0.58.0"
58+
more-itertools = "^10.0.0"
59+
numba = { version = "^0.58.0", optional = true }
6060
cad-to-shapely = { version = "^0.3.1", optional = true }
6161
rhino-shapley-interop = { version = "^0.0.4", optional = true }
6262
rhino3dm = { version = "==8.0.0b3", optional = true }
6363
pypardiso = { version = "^0.4.2", optional = true }
6464

6565
[tool.poetry.group.dev.dependencies]
66-
black = "^23.9.1"
66+
black = "^23.10.0"
6767
coverage = { extras = ["toml"], version = "^7.3.2" }
6868
darglint = "^1.8.1"
6969
flake8 = "^6.1.0"
@@ -76,12 +76,12 @@ ipykernel = "^6.25.2"
7676
ipython = "^8.16.1"
7777
ipywidgets = "^8.1.1"
7878
isort = "^5.12.0"
79-
mypy ="^1.6.0"
79+
mypy = "^1.6.1"
8080
nbconvert = "^7.9.2"
8181
nbsphinx = "^0.9.3"
82-
notebook = "^7.0.4"
82+
notebook = "^7.0.6"
8383
pep8-naming = "^0.13.3"
84-
pre-commit = "^3.4.0"
84+
pre-commit = "^3.5.0"
8585
pre-commit-hooks = "^4.5.0"
8686
Pygments = "^2.16.1"
8787
pytest = "^7.4.2"
@@ -97,6 +97,7 @@ sphinxext-opengraph = "^0.8.2"
9797
[tool.poetry.extras]
9898
dxf = ["cad-to-shapely"]
9999
rhino = ["rhino-shapley-interop", "rhino3dm"]
100+
numba = ["numba"]
100101
pardiso = ["pypardiso"]
101102

102103
[tool.poetry.scripts]

src/sectionproperties/analysis/fea.py

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,60 @@
77

88
from __future__ import annotations
99

10-
import warnings
1110
from dataclasses import dataclass, field
1211
from functools import lru_cache
13-
from typing import TYPE_CHECKING
12+
from typing import TYPE_CHECKING, Any, Callable
1413

1514
import numpy as np
1615
import numpy.typing as npt
17-
from numba import njit
18-
from numba.core.errors import NumbaPerformanceWarning
1916

2017

2118
if TYPE_CHECKING:
2219
from sectionproperties.pre.pre import Material
2320

2421

22+
# numba is an optional dependency
23+
try:
24+
from numba import njit
25+
except ImportError:
26+
27+
def njit(**options: Any) -> Callable[[Any], Any]:
28+
"""Empty decorator if numba is not installed.
29+
30+
Args:
31+
options: Optional keyword arguments for numba that are discarded.
32+
33+
Returns:
34+
Empty njit decorator.
35+
"""
36+
37+
def decorator(func: Callable[[Any], Any]) -> Callable[[Any], Any]:
38+
"""Decorator.
39+
40+
Args:
41+
func: Function to decorate.
42+
43+
Returns:
44+
Decorated function.
45+
"""
46+
47+
def wrapper(*args: Any, **kwargs: Any) -> Callable[[Any], Any]:
48+
"""Wrapper.
49+
50+
Args:
51+
args: Arguments.
52+
kwargs: Keyword arguments.
53+
54+
Returns:
55+
Wrapped function.
56+
"""
57+
return func(*args, **kwargs) # type: ignore
58+
59+
return wrapper
60+
61+
return decorator
62+
63+
2564
@njit(cache=True, nogil=True) # type: ignore
2665
def _assemble_torsion(
2766
k_el: npt.NDArray[np.float64],
@@ -587,9 +626,9 @@ def element_stress(
587626
sig_zz_myy_gp = np.zeros(n_points)
588627
sig_zz_m11_gp = np.zeros(n_points)
589628
sig_zz_m22_gp = np.zeros(n_points)
590-
sig_zxy_mzz_gp = np.zeros((n_points, 2))
591-
sig_zxy_vx_gp = np.zeros((n_points, 2))
592-
sig_zxy_vy_gp = np.zeros((n_points, 2))
629+
sig_zxy_mzz_gp = np.zeros((n_points, 2), order="F")
630+
sig_zxy_vx_gp = np.zeros((n_points, 2), order="F")
631+
sig_zxy_vy_gp = np.zeros((n_points, 2), order="F")
593632

594633
# Gauss points for 6 point Gaussian integration
595634
gps = gauss_points(n=n_points)
@@ -646,19 +685,17 @@ def element_stress(
646685
* (b.dot(phi_shear) - nu / 2 * np.array([h1, h2]))
647686
)
648687

649-
# extrapolate results to nodes, ignore numba warnings about performance
650-
with warnings.catch_warnings():
651-
warnings.simplefilter("ignore", category=NumbaPerformanceWarning)
652-
sig_zz_mxx = extrapolate_to_nodes(w=sig_zz_mxx_gp)
653-
sig_zz_myy = extrapolate_to_nodes(w=sig_zz_myy_gp)
654-
sig_zz_m11 = extrapolate_to_nodes(w=sig_zz_m11_gp)
655-
sig_zz_m22 = extrapolate_to_nodes(w=sig_zz_m22_gp)
656-
sig_zx_mzz = extrapolate_to_nodes(w=sig_zxy_mzz_gp[:, 0])
657-
sig_zy_mzz = extrapolate_to_nodes(w=sig_zxy_mzz_gp[:, 1])
658-
sig_zx_vx = extrapolate_to_nodes(w=sig_zxy_vx_gp[:, 0])
659-
sig_zy_vx = extrapolate_to_nodes(w=sig_zxy_vx_gp[:, 1])
660-
sig_zx_vy = extrapolate_to_nodes(w=sig_zxy_vy_gp[:, 0])
661-
sig_zy_vy = extrapolate_to_nodes(w=sig_zxy_vy_gp[:, 1])
688+
# extrapolate results to nodes
689+
sig_zz_mxx = extrapolate_to_nodes(w=sig_zz_mxx_gp)
690+
sig_zz_myy = extrapolate_to_nodes(w=sig_zz_myy_gp)
691+
sig_zz_m11 = extrapolate_to_nodes(w=sig_zz_m11_gp)
692+
sig_zz_m22 = extrapolate_to_nodes(w=sig_zz_m22_gp)
693+
sig_zx_mzz = extrapolate_to_nodes(w=sig_zxy_mzz_gp[:, 0])
694+
sig_zy_mzz = extrapolate_to_nodes(w=sig_zxy_mzz_gp[:, 1])
695+
sig_zx_vx = extrapolate_to_nodes(w=sig_zxy_vx_gp[:, 0])
696+
sig_zy_vx = extrapolate_to_nodes(w=sig_zxy_vx_gp[:, 1])
697+
sig_zx_vy = extrapolate_to_nodes(w=sig_zxy_vy_gp[:, 0])
698+
sig_zy_vy = extrapolate_to_nodes(w=sig_zxy_vy_gp[:, 1])
662699

663700
return (
664701
sig_zz_n,

src/sectionproperties/analysis/solver.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,9 @@ def solve_direct_lagrange(
121121
The solution vector to the linear system of equations
122122
123123
Raises:
124-
RuntimeError: If the Lagrangian multiplier method exceeds a tolerance of
125-
``1e-5``
124+
RuntimeError: If the Lagrangian multiplier method exceeds a relative tolerance
125+
of ``1e-7`` or absolute tolerance related to your machine's floating point
126+
precision.
126127
"""
127128
u = sp_solve(A=k_lg, b=np.append(f, 0))
128129

@@ -131,8 +132,11 @@ def solve_direct_lagrange(
131132
rel_error = multiplier / max(np.absolute(u))
132133

133134
if rel_error > 1e-7 and multiplier > 10.0 * np.finfo(float).eps:
134-
msg = "Lagrangian multiplier method error exceeds tolerance of 1e-5."
135-
raise RuntimeError(msg)
135+
raise RuntimeError(
136+
"Lagrangian multiplier method error exceeds the prescribed tolerance, "
137+
"consider refining your mesh. If this error is unexpected raise an issue "
138+
"at https://github.com/robbievanleeuwen/section-properties/issues."
139+
)
136140

137141
return u[:-1] # type: ignore
138142

0 commit comments

Comments
 (0)