simgeometry 0.1.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 (67) hide show
  1. simgeometry-0.1.0/LICENSE.txt +21 -0
  2. simgeometry-0.1.0/PKG-INFO +128 -0
  3. simgeometry-0.1.0/README.md +65 -0
  4. simgeometry-0.1.0/pyproject.toml +90 -0
  5. simgeometry-0.1.0/setup.cfg +4 -0
  6. simgeometry-0.1.0/src/simgeometry/__init__.py +38 -0
  7. simgeometry-0.1.0/src/simgeometry/_bounds.py +16 -0
  8. simgeometry-0.1.0/src/simgeometry/_normalize.py +23 -0
  9. simgeometry-0.1.0/src/simgeometry/_particle_boundaries.py +37 -0
  10. simgeometry-0.1.0/src/simgeometry/_types.py +22 -0
  11. simgeometry-0.1.0/src/simgeometry/api.py +247 -0
  12. simgeometry-0.1.0/src/simgeometry/boundingbox.py +231 -0
  13. simgeometry-0.1.0/src/simgeometry/collection.py +65 -0
  14. simgeometry-0.1.0/src/simgeometry/crossings.py +319 -0
  15. simgeometry-0.1.0/src/simgeometry/cut_edges.py +309 -0
  16. simgeometry-0.1.0/src/simgeometry/cylindrical.py +43 -0
  17. simgeometry-0.1.0/src/simgeometry/domain_decomposition.py +496 -0
  18. simgeometry-0.1.0/src/simgeometry/evaluation.py +105 -0
  19. simgeometry-0.1.0/src/simgeometry/fractions.py +68 -0
  20. simgeometry-0.1.0/src/simgeometry/grid.py +238 -0
  21. simgeometry-0.1.0/src/simgeometry/kernels/__init__.py +1 -0
  22. simgeometry-0.1.0/src/simgeometry/kernels/_build.py +53 -0
  23. simgeometry-0.1.0/src/simgeometry/kernels/_metal.py +41 -0
  24. simgeometry-0.1.0/src/simgeometry/kernels/compile.py +24 -0
  25. simgeometry-0.1.0/src/simgeometry/kernels/contains_ball/__init__.py +12 -0
  26. simgeometry-0.1.0/src/simgeometry/kernels/contains_ball/contains_ball_cuda.cu +27 -0
  27. simgeometry-0.1.0/src/simgeometry/kernels/contains_ball/contains_ball_metal.py +53 -0
  28. simgeometry-0.1.0/src/simgeometry/kernels/contains_ball/contains_ball_numpy.py +23 -0
  29. simgeometry-0.1.0/src/simgeometry/kernels/contains_ball/contains_ball_pyccel.py +31 -0
  30. simgeometry-0.1.0/src/simgeometry/kernels/contains_box/__init__.py +12 -0
  31. simgeometry-0.1.0/src/simgeometry/kernels/contains_box/contains_box_cuda.cu +26 -0
  32. simgeometry-0.1.0/src/simgeometry/kernels/contains_box/contains_box_metal.py +50 -0
  33. simgeometry-0.1.0/src/simgeometry/kernels/contains_box/contains_box_numpy.py +24 -0
  34. simgeometry-0.1.0/src/simgeometry/kernels/contains_box/contains_box_pyccel.py +32 -0
  35. simgeometry-0.1.0/src/simgeometry/kernels/contains_polygon_2d/__init__.py +12 -0
  36. simgeometry-0.1.0/src/simgeometry/kernels/contains_polygon_2d/contains_polygon_2d_cuda.cu +35 -0
  37. simgeometry-0.1.0/src/simgeometry/kernels/contains_polygon_2d/contains_polygon_2d_metal.py +58 -0
  38. simgeometry-0.1.0/src/simgeometry/kernels/contains_polygon_2d/contains_polygon_2d_numpy.py +28 -0
  39. simgeometry-0.1.0/src/simgeometry/kernels/contains_polygon_2d/contains_polygon_2d_pyccel.py +40 -0
  40. simgeometry-0.1.0/src/simgeometry/mesh.py +147 -0
  41. simgeometry-0.1.0/src/simgeometry/objects/__init__.py +35 -0
  42. simgeometry-0.1.0/src/simgeometry/objects/aperture2d.py +183 -0
  43. simgeometry-0.1.0/src/simgeometry/objects/aperture3d.py +361 -0
  44. simgeometry-0.1.0/src/simgeometry/objects/circle.py +138 -0
  45. simgeometry-0.1.0/src/simgeometry/objects/cuboid.py +173 -0
  46. simgeometry-0.1.0/src/simgeometry/objects/function_object.py +214 -0
  47. simgeometry-0.1.0/src/simgeometry/objects/line.py +127 -0
  48. simgeometry-0.1.0/src/simgeometry/objects/polygon.py +182 -0
  49. simgeometry-0.1.0/src/simgeometry/objects/polyline.py +67 -0
  50. simgeometry-0.1.0/src/simgeometry/objects/rectangle.py +130 -0
  51. simgeometry-0.1.0/src/simgeometry/objects/sphere.py +181 -0
  52. simgeometry-0.1.0/src/simgeometry/objects/triangle.py +148 -0
  53. simgeometry-0.1.0/src/simgeometry/operations.py +386 -0
  54. simgeometry-0.1.0/src/simgeometry/panels.py +80 -0
  55. simgeometry-0.1.0/src/simgeometry/plotting.py +179 -0
  56. simgeometry-0.1.0/src/simgeometry/py.typed +0 -0
  57. simgeometry-0.1.0/src/simgeometry/queries.py +445 -0
  58. simgeometry-0.1.0/src/simgeometry/sampling.py +75 -0
  59. simgeometry-0.1.0/src/simgeometry/shapes.py +402 -0
  60. simgeometry-0.1.0/src/simgeometry/simulation_domain.py +277 -0
  61. simgeometry-0.1.0/src/simgeometry/utils.py +24 -0
  62. simgeometry-0.1.0/src/simgeometry/visualization.py +381 -0
  63. simgeometry-0.1.0/src/simgeometry.egg-info/PKG-INFO +128 -0
  64. simgeometry-0.1.0/src/simgeometry.egg-info/SOURCES.txt +65 -0
  65. simgeometry-0.1.0/src/simgeometry.egg-info/dependency_links.txt +1 -0
  66. simgeometry-0.1.0/src/simgeometry.egg-info/requires.txt +57 -0
  67. simgeometry-0.1.0/src/simgeometry.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Max Lindqvist
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.4
2
+ Name: simgeometry
3
+ Version: 0.1.0
4
+ Summary: Shapes, grids, and simulation domains for numerical simulations
5
+ Author: Max
6
+ License-Expression: MIT
7
+ Project-URL: Source, https://github.com/max-models/simgeometry
8
+ Keywords: geometry,grids,simulation,mpi
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE.txt
19
+ Requires-Dist: cunumpy>=0.6.2
20
+ Requires-Dist: maybempi>=0.1
21
+ Requires-Dist: mpiarray>=0.1.0
22
+ Requires-Dist: numpy
23
+ Provides-Extra: dev
24
+ Requires-Dist: jupyterlab; extra == "dev"
25
+ Requires-Dist: pre-commit; extra == "dev"
26
+ Requires-Dist: pyproject-fmt; extra == "dev"
27
+ Requires-Dist: pyright; extra == "dev"
28
+ Requires-Dist: ruff; extra == "dev"
29
+ Requires-Dist: simgeometry[docs,test]; extra == "dev"
30
+ Provides-Extra: docs
31
+ Requires-Dist: griffe; extra == "docs"
32
+ Requires-Dist: simgeometry[clip,plot]; extra == "docs"
33
+ Requires-Dist: ipykernel; extra == "docs"
34
+ Requires-Dist: matplotlib>=3.10.9; extra == "docs"
35
+ Requires-Dist: nbclient>=0.11; extra == "docs"
36
+ Requires-Dist: nbformat>=5.11.1; extra == "docs"
37
+ Provides-Extra: clip
38
+ Requires-Dist: shapely>=2; extra == "clip"
39
+ Provides-Extra: evaluate
40
+ Requires-Dist: xarray; extra == "evaluate"
41
+ Provides-Extra: mesh
42
+ Requires-Dist: scikit-image>=0.22; extra == "mesh"
43
+ Provides-Extra: plot
44
+ Requires-Dist: matplotlib>=3.10; extra == "plot"
45
+ Requires-Dist: simgeometry[evaluate,mesh]; extra == "plot"
46
+ Provides-Extra: interactive
47
+ Requires-Dist: pyvista>=0.44; extra == "interactive"
48
+ Requires-Dist: simgeometry[plot]; extra == "interactive"
49
+ Provides-Extra: mpi
50
+ Requires-Dist: mpi4py; extra == "mpi"
51
+ Provides-Extra: pyccel
52
+ Requires-Dist: pyccel>2.0; extra == "pyccel"
53
+ Provides-Extra: gpu
54
+ Requires-Dist: cupy-cuda12x; extra == "gpu"
55
+ Provides-Extra: metal
56
+ Requires-Dist: mlx; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "metal"
57
+ Provides-Extra: test
58
+ Requires-Dist: mpi4py; extra == "test"
59
+ Requires-Dist: pytest; extra == "test"
60
+ Requires-Dist: pytest-cov; extra == "test"
61
+ Requires-Dist: simgeometry[clip]; extra == "test"
62
+ Dynamic: license-file
63
+
64
+ # simgeometry
65
+
66
+
67
+ Geometry primitives for numerical simulations: bounded domains,
68
+ structured grids, MPI domain decomposition, and 1D, 2D, and 3D shapes.
69
+ Box, ball, and polygon containment have NumPy, Pyccel, CUDA, and Metal
70
+ implementations. Originally developed for
71
+ [Picnic](https://github.com/max-models/picnic).
72
+
73
+ ## Install
74
+
75
+ ``` bash
76
+ pip install simgeometry
77
+ ```
78
+
79
+ For development, install this checkout with `pip install -e '.[test]'`.
80
+ NumPy, cunumpy, maybempi, and mpiarray are runtime dependencies.
81
+ Matplotlib is optional. Install `simgeometry[plot]` for plotting,
82
+ labelled evaluation and surface meshing, or `simgeometry[interactive]`
83
+ for interactive 3D clipping with PyVista. Install `simgeometry[mpi]` for
84
+ MPI, `simgeometry[pyccel]` for compiled CPU containment kernels, or
85
+ `simgeometry[gpu]` for CUDA.
86
+
87
+ ## Example
88
+
89
+ ``` python
90
+ from simgeometry.grid import Grid
91
+ from simgeometry.objects import Circle
92
+
93
+ boundary = Circle(midpoint=(0.5, 0.5), radius=0.25)
94
+ grid = Grid(ndim=2, lower_bound=(0, 0), upper_bound=(1, 1), num_gridpoints=(32, 32))
95
+ mask = boundary.node_mask(grid)
96
+ ```
97
+
98
+ `SimulationDomain` accepts field and particle boundary objects through
99
+ their `get_bc(dir=..., side=...).bc_type` interface. Applications may
100
+ supply a seeded random function with `BoundingBox.random` and an
101
+ accelerated particle boundary implementation with
102
+ `SimulationDomain.boundary_kernel`.
103
+
104
+ ## Inspect, slice, and compose
105
+
106
+ ``` python
107
+ from simgeometry import Sphere
108
+
109
+ shell = Sphere((0, 0, 0), 1) - Sphere((0, 0, 0), 0.4)
110
+ shell.show_3d(opacity=0.6)
111
+ shell.slice(z=0.2).show()
112
+ inside = shell.evaluate(x=[0, 0.8], y=0, z=0)
113
+ ```
114
+
115
+ Shapes support named collections, Boolean operations, affine transforms,
116
+ surface queries, point sampling, mesh export, cut-edge geometry and
117
+ approximate cell/face fractions. See the [executed
118
+ tutorials](https://max-models.github.io/simgeometry/tutorials/) and [API
119
+ guide](https://max-models.github.io/simgeometry/getting-started/geometry-api/)
120
+ for examples and the accuracy limits of sampled operations.
121
+
122
+ ## Development
123
+
124
+ ``` bash
125
+ pytest src/simgeometry/tests
126
+ ```
127
+
128
+ Documentation: <https://max-models.github.io/simgeometry/>
@@ -0,0 +1,65 @@
1
+ # simgeometry
2
+
3
+
4
+ Geometry primitives for numerical simulations: bounded domains,
5
+ structured grids, MPI domain decomposition, and 1D, 2D, and 3D shapes.
6
+ Box, ball, and polygon containment have NumPy, Pyccel, CUDA, and Metal
7
+ implementations. Originally developed for
8
+ [Picnic](https://github.com/max-models/picnic).
9
+
10
+ ## Install
11
+
12
+ ``` bash
13
+ pip install simgeometry
14
+ ```
15
+
16
+ For development, install this checkout with `pip install -e '.[test]'`.
17
+ NumPy, cunumpy, maybempi, and mpiarray are runtime dependencies.
18
+ Matplotlib is optional. Install `simgeometry[plot]` for plotting,
19
+ labelled evaluation and surface meshing, or `simgeometry[interactive]`
20
+ for interactive 3D clipping with PyVista. Install `simgeometry[mpi]` for
21
+ MPI, `simgeometry[pyccel]` for compiled CPU containment kernels, or
22
+ `simgeometry[gpu]` for CUDA.
23
+
24
+ ## Example
25
+
26
+ ``` python
27
+ from simgeometry.grid import Grid
28
+ from simgeometry.objects import Circle
29
+
30
+ boundary = Circle(midpoint=(0.5, 0.5), radius=0.25)
31
+ grid = Grid(ndim=2, lower_bound=(0, 0), upper_bound=(1, 1), num_gridpoints=(32, 32))
32
+ mask = boundary.node_mask(grid)
33
+ ```
34
+
35
+ `SimulationDomain` accepts field and particle boundary objects through
36
+ their `get_bc(dir=..., side=...).bc_type` interface. Applications may
37
+ supply a seeded random function with `BoundingBox.random` and an
38
+ accelerated particle boundary implementation with
39
+ `SimulationDomain.boundary_kernel`.
40
+
41
+ ## Inspect, slice, and compose
42
+
43
+ ``` python
44
+ from simgeometry import Sphere
45
+
46
+ shell = Sphere((0, 0, 0), 1) - Sphere((0, 0, 0), 0.4)
47
+ shell.show_3d(opacity=0.6)
48
+ shell.slice(z=0.2).show()
49
+ inside = shell.evaluate(x=[0, 0.8], y=0, z=0)
50
+ ```
51
+
52
+ Shapes support named collections, Boolean operations, affine transforms,
53
+ surface queries, point sampling, mesh export, cut-edge geometry and
54
+ approximate cell/face fractions. See the [executed
55
+ tutorials](https://max-models.github.io/simgeometry/tutorials/) and [API
56
+ guide](https://max-models.github.io/simgeometry/getting-started/geometry-api/)
57
+ for examples and the accuracy limits of sampled operations.
58
+
59
+ ## Development
60
+
61
+ ``` bash
62
+ pytest src/simgeometry/tests
63
+ ```
64
+
65
+ Documentation: <https://max-models.github.io/simgeometry/>
@@ -0,0 +1,90 @@
1
+ [build-system]
2
+ build-backend = "setuptools.build_meta"
3
+ requires = [ "setuptools", "wheel" ]
4
+
5
+ [project]
6
+ name = "simgeometry"
7
+ version = "0.1.0"
8
+ description = "Shapes, grids, and simulation domains for numerical simulations"
9
+ readme = "README.md"
10
+ keywords = [ "geometry", "grids", "simulation", "mpi" ]
11
+ license = "MIT"
12
+ license-files = [ "LICENSE.txt" ]
13
+ authors = [ { name = "Max" } ]
14
+ requires-python = ">=3.10"
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
23
+ ]
24
+ dependencies = [
25
+ "cunumpy>=0.6.2",
26
+ "maybempi>=0.1",
27
+ "mpiarray>=0.1.0",
28
+ "numpy",
29
+ ]
30
+ optional-dependencies.dev = [
31
+ "jupyterlab",
32
+ "pre-commit",
33
+ "pyproject-fmt",
34
+ "pyright",
35
+ "ruff",
36
+ "simgeometry[docs,test]",
37
+ ]
38
+ optional-dependencies.docs = [
39
+ "griffe",
40
+ "simgeometry[clip,plot]",
41
+ "ipykernel",
42
+ "matplotlib>=3.10.9",
43
+ "nbclient>=0.11",
44
+ "nbformat>=5.11.1",
45
+ ]
46
+ optional-dependencies.clip = [ "shapely>=2" ]
47
+ optional-dependencies.evaluate = [ "xarray" ]
48
+ optional-dependencies.mesh = [ "scikit-image>=0.22" ]
49
+ optional-dependencies.plot = [ "matplotlib>=3.10", "simgeometry[evaluate,mesh]" ]
50
+ optional-dependencies.interactive = [ "pyvista>=0.44", "simgeometry[plot]" ]
51
+ optional-dependencies.mpi = [ "mpi4py" ]
52
+ optional-dependencies.pyccel = [ "pyccel>2.0" ]
53
+ optional-dependencies.gpu = [ "cupy-cuda12x" ]
54
+ optional-dependencies.metal = [ "mlx; sys_platform == 'darwin' and platform_machine == 'arm64'" ]
55
+ optional-dependencies.test = [ "mpi4py", "pytest", "pytest-cov", "simgeometry[clip]" ]
56
+ urls.Source = "https://github.com/max-models/simgeometry"
57
+
58
+ [tool.setuptools]
59
+ package-data."*" = [ "py.typed" ]
60
+ package-data.simgeometry = [ "kernels/*/*.cu" ]
61
+ packages.find.where = [ "src" ]
62
+ packages.find.exclude = [ "simgeometry.tests*" ]
63
+
64
+ [tool.ruff]
65
+ target-version = "py310"
66
+ line-length = 88
67
+ extend-include = [ "*.ipynb" ]
68
+ # Keep linting focused while the geometry code retains its existing docstrings.
69
+ lint.select = [ "E", "F", "I", "W" ]
70
+ lint.ignore = [ "E501" ] # line length is handled by the formatter
71
+ lint.per-file-ignores."**/tests/**" = [ "E402" ]
72
+ lint.pydocstyle.convention = "google"
73
+
74
+ [tool.pyright]
75
+ include = [ "src" ]
76
+ exclude = [ "**/tests" ]
77
+ pythonVersion = "3.10"
78
+ # The extracted code predates strict typing; keep import resolution checked.
79
+ typeCheckingMode = "off"
80
+ reportMissingImports = "error"
81
+
82
+ [tool.pytest]
83
+ ini_options.pythonpath = [ "src" ]
84
+ ini_options.testpaths = [ "src" ]
85
+ ini_options.addopts = "-ra"
86
+
87
+ [tool.coverage]
88
+ run.omit = [ "*/tests/*" ]
89
+ run.source = [ "simgeometry" ]
90
+ report.show_missing = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,38 @@
1
+ """Shapes, grids, and domains for numerical simulations."""
2
+
3
+ from simgeometry.collection import GeometryCollection
4
+ from simgeometry.grid import Grid
5
+ from simgeometry.objects import (
6
+ Aperture2D,
7
+ Aperture3D,
8
+ Circle,
9
+ Cuboid,
10
+ FunctionObject2D,
11
+ FunctionObject3D,
12
+ Line,
13
+ Polygon,
14
+ Polyline,
15
+ Rectangle,
16
+ Sphere,
17
+ Triangle,
18
+ )
19
+ from simgeometry.simulation_domain import SimulationDomain
20
+
21
+ __version__ = "0.1.0"
22
+ __all__ = [
23
+ "GeometryCollection",
24
+ "Grid",
25
+ "SimulationDomain",
26
+ "Aperture2D",
27
+ "Aperture3D",
28
+ "Circle",
29
+ "Cuboid",
30
+ "FunctionObject2D",
31
+ "FunctionObject3D",
32
+ "Line",
33
+ "Polygon",
34
+ "Polyline",
35
+ "Rectangle",
36
+ "Sphere",
37
+ "Triangle",
38
+ ]
@@ -0,0 +1,16 @@
1
+ """Array bounds shared by geometric regions and grids."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ class Bounds:
7
+ def __init__(self, lower_bound, upper_bound) -> None:
8
+ assert len(lower_bound) == len(upper_bound)
9
+ self.lower_bound = lower_bound
10
+ self.upper_bound = upper_bound
11
+ self.ndim = len(lower_bound)
12
+ assert self.ndim in (1, 2, 3)
13
+ for axis in range(self.ndim):
14
+ assert upper_bound[axis] >= lower_bound[axis]
15
+ self.sidelengths = upper_bound - lower_bound
16
+ self.midpoint = lower_bound + 0.5 * self.sidelengths
@@ -0,0 +1,23 @@
1
+ """Normalize scalar and sequence geometry arguments."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+
7
+
8
+ def ensure_dim_tuple(value: object, *, ndim: int | None = None) -> tuple:
9
+ if isinstance(value, tuple):
10
+ normalized = value
11
+ elif isinstance(value, list):
12
+ normalized = tuple(value)
13
+ elif isinstance(value, (str, bytes, dict)):
14
+ raise TypeError(
15
+ f"value must be a scalar number/bool or sequence, got {type(value)}"
16
+ )
17
+ elif isinstance(value, Iterable):
18
+ normalized = tuple(value)
19
+ else:
20
+ normalized = (value,)
21
+ if ndim is not None and len(normalized) != ndim:
22
+ raise ValueError(f"value must have length {ndim}, got {len(normalized)}")
23
+ return normalized
@@ -0,0 +1,37 @@
1
+ """Apply particle boundary conditions on the active array backend."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import cunumpy as xp
6
+
7
+
8
+ def apply_particle_boundaries(
9
+ positions, velocities, alive, reinject, lower, upper, lower_type, upper_type
10
+ ) -> None:
11
+ """Update component-major particle arrays in place.
12
+
13
+ Boundary codes are kill=0, reflect=1, periodic=2, reinject=3.
14
+ """
15
+ reinject[:] = False
16
+ in_domain = alive.copy()
17
+ for axis in range(positions.shape[0]):
18
+ active = alive & ~reinject
19
+ x = positions[axis]
20
+ low, high = lower[axis], upper[axis]
21
+ below = active & (x < low)
22
+ above = active & ((x >= high) if upper_type[axis] == 2 else (x > high))
23
+ for mask, bound, side_type in (
24
+ (below, low, lower_type[axis]),
25
+ (above, high, upper_type[axis]),
26
+ ):
27
+ if side_type == 1:
28
+ x[mask] = 2.0 * bound - x[mask]
29
+ velocities[axis, mask] *= -1.0
30
+ elif side_type == 2:
31
+ wrapped = low + (x[mask] - low) % (high - low)
32
+ x[mask] = xp.where(wrapped >= high, low, wrapped)
33
+ elif side_type == 3:
34
+ reinject |= mask
35
+ checked = alive & ~reinject
36
+ in_domain &= ~checked | ((x >= low) & (x < high))
37
+ alive &= in_domain
@@ -0,0 +1,22 @@
1
+ """Types used by geometry without importing simulation utilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Sequence
6
+ from typing import TypeAlias
7
+
8
+ from numpy import ndarray
9
+
10
+ Array: TypeAlias = ndarray
11
+ Scalar: TypeAlias = str | int | float | bool | None
12
+ ConfigValue: TypeAlias = (
13
+ Scalar
14
+ | Array
15
+ | list["ConfigValue"]
16
+ | tuple["ConfigValue", ...]
17
+ | set["ConfigValue"]
18
+ | dict[str, "ConfigValue"]
19
+ )
20
+ Printable: TypeAlias = str | int | float | bool | None
21
+ BoundsLike: TypeAlias = Sequence[int | float] | ndarray
22
+ Vertices2DLike: TypeAlias = Sequence[BoundsLike] | ndarray