fiesta-pkg 1.0.2__py3-none-any.whl

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 (91) hide show
  1. docs/source/conf.py +56 -0
  2. fiesta/__init__.py +12 -0
  3. fiesta/boundary/__init__.py +18 -0
  4. fiesta/boundary/mpi_periodic.py +216 -0
  5. fiesta/boundary/mpi_randoms.py +215 -0
  6. fiesta/boundary/periodic.py +322 -0
  7. fiesta/boundary/randoms.py +167 -0
  8. fiesta/coords/__init__.py +16 -0
  9. fiesta/coords/mpi_points.py +639 -0
  10. fiesta/coords/points.py +153 -0
  11. fiesta/dtfe/__init__.py +19 -0
  12. fiesta/dtfe/dtfe2d.py +562 -0
  13. fiesta/dtfe/dtfe3d.py +759 -0
  14. fiesta/dtfe/dtfe4grid.py +1709 -0
  15. fiesta/dtfe/mpi_dtfe4grid.py +1146 -0
  16. fiesta/gridsph/__init__.py +9 -0
  17. fiesta/gridsph/gridsph.py +221 -0
  18. fiesta/gridsph/integral_image.py +46 -0
  19. fiesta/gridsph/mpi_gridsph.py +412 -0
  20. fiesta/interp/__init__.py +6 -0
  21. fiesta/interp/bilinear.py +273 -0
  22. fiesta/interp/trilinear.py +339 -0
  23. fiesta/kdtree/__init__.py +3 -0
  24. fiesta/kdtree/kdtree1d.py +87 -0
  25. fiesta/kdtree/kdtree2d.py +97 -0
  26. fiesta/kdtree/kdtree3d.py +112 -0
  27. fiesta/maths/__init__.py +10 -0
  28. fiesta/maths/diff.py +213 -0
  29. fiesta/maths/matrix.py +122 -0
  30. fiesta/maths/mpi_diff.py +116 -0
  31. fiesta/p2g/__init__.py +11 -0
  32. fiesta/p2g/deconvol.py +255 -0
  33. fiesta/p2g/mpi_part2grid.py +271 -0
  34. fiesta/p2g/part2grid.py +214 -0
  35. fiesta/randoms/__init__.py +3 -0
  36. fiesta/randoms/cartesian.py +102 -0
  37. fiesta/sph/__init__.py +12 -0
  38. fiesta/sph/kernels.py +87 -0
  39. fiesta/sph/mpi_sph4grid.py +312 -0
  40. fiesta/sph/sph1d.py +167 -0
  41. fiesta/sph/sph2d.py +167 -0
  42. fiesta/sph/sph3d.py +174 -0
  43. fiesta/sph/sph4grid.py +269 -0
  44. fiesta/src/__init__.py +69 -0
  45. fiesta/src/bilinear.py +307 -0
  46. fiesta/src/delaunay2d.py +190 -0
  47. fiesta/src/delaunay3d.py +244 -0
  48. fiesta/src/differentiate.py +248 -0
  49. fiesta/src/grid.py +52 -0
  50. fiesta/src/gridsph.py +831 -0
  51. fiesta/src/matrix.py +147 -0
  52. fiesta/src/part2grid_2d.py +291 -0
  53. fiesta/src/part2grid_3d.py +346 -0
  54. fiesta/src/part2grid_pix.py +306 -0
  55. fiesta/src/part2grid_wei.py +105 -0
  56. fiesta/src/polygon.py +72 -0
  57. fiesta/src/polyhedron.py +46 -0
  58. fiesta/src/trilinear.py +429 -0
  59. fiesta/src/voronoi2d.py +96 -0
  60. fiesta/src/voronoi3d.py +111 -0
  61. fiesta/utils/__init__.py +7 -0
  62. fiesta/utils/complex.py +37 -0
  63. fiesta/utils/lists.py +15 -0
  64. fiesta/utils/vectors.py +41 -0
  65. fiesta_pkg-1.0.2.dist-info/METADATA +146 -0
  66. fiesta_pkg-1.0.2.dist-info/RECORD +91 -0
  67. fiesta_pkg-1.0.2.dist-info/WHEEL +5 -0
  68. fiesta_pkg-1.0.2.dist-info/top_level.txt +3 -0
  69. tests/mpi_tests/test_mpi_boundary.py +194 -0
  70. tests/mpi_tests/test_mpi_coords.py +373 -0
  71. tests/mpi_tests/test_mpi_diff.py +113 -0
  72. tests/mpi_tests/test_mpi_dtfe4grid.py +245 -0
  73. tests/mpi_tests/test_mpi_gridsph.py +377 -0
  74. tests/mpi_tests/test_mpi_interp.py +340 -0
  75. tests/mpi_tests/test_mpi_part2grid.py +227 -0
  76. tests/mpi_tests/test_mpi_randoms.py +108 -0
  77. tests/mpi_tests/test_mpi_routines.py +215 -0
  78. tests/mpi_tests/test_mpi_sph4grid.py +353 -0
  79. tests/normal_tests/test_boundary.py +126 -0
  80. tests/normal_tests/test_coords.py +91 -0
  81. tests/normal_tests/test_dtfe.py +747 -0
  82. tests/normal_tests/test_gridsph.py +456 -0
  83. tests/normal_tests/test_interp.py +106 -0
  84. tests/normal_tests/test_kdtree.py +79 -0
  85. tests/normal_tests/test_maths.py +52 -0
  86. tests/normal_tests/test_mpi_dtfe4grid.py +339 -0
  87. tests/normal_tests/test_p2g.py +178 -0
  88. tests/normal_tests/test_randoms.py +26 -0
  89. tests/normal_tests/test_sph.py +128 -0
  90. tests/normal_tests/test_sph4grid.py +331 -0
  91. tests/normal_tests/test_utils.py +45 -0
docs/source/conf.py ADDED
@@ -0,0 +1,56 @@
1
+ # Configuration file for the Sphinx documentation builder.
2
+ import os
3
+ import sys
4
+
5
+ sys.path.insert(0, os.path.abspath("../.."))
6
+
7
+ import vinfo
8
+
9
+ # -- Project information
10
+
11
+ project = "FIESTA"
12
+ copyright = "2021-2026, Krishna Naidoo"
13
+ author = "Krishna Naidoo"
14
+
15
+ version = vinfo.vstr
16
+
17
+ # -- General configuration
18
+
19
+ extensions = [
20
+ "sphinx.ext.duration",
21
+ "sphinx.ext.doctest",
22
+ "sphinx.ext.autodoc",
23
+ "sphinx.ext.autosummary",
24
+ "sphinx.ext.intersphinx",
25
+ "sphinx.ext.napoleon",
26
+ "sphinx.ext.mathjax",
27
+ "sphinx_simplepdf",
28
+ ]
29
+
30
+ source_suffix = [".rst", ".md"]
31
+
32
+ # Napoleon settings
33
+ napoleon_numpy_docstring = True
34
+
35
+ intersphinx_mapping = {
36
+ "python": ("https://docs.python.org/3/", None),
37
+ "sphinx": ("https://www.sphinx-doc.org/en/master/", None),
38
+ }
39
+ intersphinx_disabled_domains = ["std"]
40
+
41
+ templates_path = ["_templates"]
42
+
43
+
44
+ # -- Options for HTML output
45
+
46
+ # html_theme = 'sphinx_rtd_theme'
47
+ html_theme = "furo"
48
+
49
+ html_static_path = ["_static"]
50
+ html_theme_options = {
51
+ "light_logo": "FiEsta_logo_small_white.jpg",
52
+ "dark_logo": "FiEsta_logo_small_black.jpg",
53
+ }
54
+
55
+ # -- Options for EPUB output
56
+ epub_show_urls = "footnote"
fiesta/__init__.py ADDED
@@ -0,0 +1,12 @@
1
+ from . import boundary
2
+ from . import coords
3
+ from . import dtfe
4
+ from . import maths
5
+ from . import p2g
6
+ from . import interp
7
+ from . import kdtree
8
+ from . import randoms
9
+ from . import sph
10
+ from . import src
11
+ from . import utils
12
+ from . import gridsph
@@ -0,0 +1,18 @@
1
+ from .periodic import buffer_periodic
2
+ from .periodic import subbox_buffer_periodic
3
+ from .periodic import buffer_periodic_2D
4
+ from .periodic import subbox_buffer_periodic_2D
5
+ from .periodic import buffer_periodic_3D
6
+ from .periodic import subbox_buffer_periodic_3D
7
+
8
+ from .randoms import buffer_random_2D
9
+ from .randoms import buffer_random_3D
10
+
11
+ from .mpi_periodic import mpi_buffer_internal_2D
12
+ from .mpi_periodic import mpi_buffer_internal_3D
13
+ from .mpi_periodic import mpi_buffer_periodic_2D
14
+ from .mpi_periodic import mpi_buffer_periodic_3D
15
+
16
+ from .mpi_randoms import mpi_buffer_random_2D
17
+ from .mpi_randoms import mpi_buffer_random_3D
18
+ from .mpi_randoms import mpi_buffer_random_utils
@@ -0,0 +1,216 @@
1
+ import numpy as np
2
+
3
+ from . import periodic
4
+
5
+ from typing import Union, List
6
+
7
+
8
+ def mpi_buffer_internal_2D(
9
+ data: np.ndarray,
10
+ boxsize: float,
11
+ buffer_length: float,
12
+ MPI: object,
13
+ origin: float = 0.0,
14
+ ) -> np.ndarray:
15
+ """
16
+ Internal buffer particles between partitions are moved up and down.
17
+
18
+ Parameters
19
+ ----------
20
+ data : array
21
+ Where columns 0 and 1 correspond to the x and y coordinates.
22
+ xboxsize : float
23
+ Boxsize along x-axis.
24
+ buffer_length : float
25
+ Length of the buffer region.
26
+ MPI : class object
27
+ MPIutils MPI class object.
28
+ origin : float, optional
29
+ Origin point.
30
+
31
+ Returns
32
+ -------
33
+ datap : array
34
+ Periodic data values.
35
+ """
36
+ if np.isscalar(origin):
37
+ xorigin = origin
38
+ else:
39
+ xorigin = origin[0]
40
+ if np.isscalar(boxsize):
41
+ xboxsize = boxsize
42
+ else:
43
+ xboxsize = boxsize[0]
44
+ cond = np.where(data[:, 0] <= xorigin + buffer_length)[0]
45
+ data_send_down = MPI.send_down(data[cond])
46
+ cond = np.where(data[:, 0] >= xorigin + xboxsize - buffer_length)[0]
47
+ data_send_up = MPI.send_up(data[cond])
48
+ if MPI.rank == 0:
49
+ # data_send_up[:,0] -= xboxsize
50
+ datap = np.vstack([data, data_send_down])
51
+ elif MPI.rank == MPI.size - 1:
52
+ # data_send_down[:,0] += xboxsize
53
+ datap = np.vstack([data, data_send_up])
54
+ else:
55
+ datap = np.vstack([data, data_send_down, data_send_up])
56
+ return datap
57
+
58
+
59
+ def mpi_buffer_periodic_2D(
60
+ data: np.ndarray,
61
+ boxsize: Union[float, List[float]],
62
+ buffer_length: float,
63
+ MPI: object,
64
+ origin: Union[float, List[float]] = 0.0,
65
+ include_internal: bool = True,
66
+ ) -> np.ndarray:
67
+ """
68
+ Generates random buffer particles around a 2D box.
69
+
70
+ Parameters
71
+ ----------
72
+ data : array
73
+ Where columns 0 and 1 are x and y.
74
+ boxsize : float or list
75
+ Boxsize.
76
+ buffer_length : float
77
+ Length of the buffer region.
78
+ MPI : class object
79
+ MPIutils MPI class object.
80
+ origin : float or list, optional
81
+ Origin point.
82
+ include_internal : bool, optional
83
+ Whether to include internal buffer particles.
84
+
85
+ Returns
86
+ -------
87
+ datap : array
88
+ Periodic data values.
89
+ """
90
+ if np.isscalar(origin):
91
+ xorigin, yorigin = origin, origin
92
+ else:
93
+ xorigin, yorigin = origin[0], origin[1]
94
+ if np.isscalar(boxsize):
95
+ xboxsize, yboxsize = boxsize, boxsize
96
+ else:
97
+ xboxsize, yboxsize = boxsize[0], boxsize[1]
98
+ datap = periodic.buffer_periodic(data, 1, yboxsize, buffer_length, origin=yorigin)
99
+ cond = np.where(datap[:, 0] <= xorigin + buffer_length)[0]
100
+ data_send_down = MPI.send_down(datap[cond])
101
+ cond = np.where(datap[:, 0] >= xorigin + xboxsize - buffer_length)[0]
102
+ data_send_up = MPI.send_up(datap[cond])
103
+ if MPI.rank == 0:
104
+ data_send_up[:, 0] -= xboxsize
105
+ elif MPI.rank == MPI.size - 1:
106
+ data_send_down[:, 0] += xboxsize
107
+ datap = np.vstack([datap, data_send_down, data_send_up])
108
+ if include_internal:
109
+ datap = mpi_buffer_internal_2D(datap, boxsize, buffer_length, MPI, origin)
110
+ return datap
111
+
112
+
113
+ def mpi_buffer_internal_3D(
114
+ data: np.ndarray,
115
+ boxsize: float,
116
+ buffer_length: float,
117
+ MPI: object,
118
+ origin: float = 0.0,
119
+ ) -> np.ndarray:
120
+ """
121
+ Internal buffer particles between partitions are moved up and down.
122
+
123
+ Parameters
124
+ ----------
125
+ data : array
126
+ Where columns 0, 1 and 2 correspond to the x, y and z coordinates.
127
+ xboxsize : float
128
+ Boxsize along x-axis.
129
+ buffer_length : float
130
+ Length of the buffer region.
131
+ MPI : class object
132
+ MPIutils MPI class object.
133
+ origin : float, optional
134
+ Origin point.
135
+
136
+ Returns
137
+ -------
138
+ datap : array
139
+ Periodic data values.
140
+ """
141
+ if np.isscalar(origin):
142
+ xorigin = origin
143
+ else:
144
+ xorigin = origin[0]
145
+ if np.isscalar(boxsize):
146
+ xboxsize = boxsize
147
+ else:
148
+ xboxsize = boxsize[0]
149
+ cond = np.where(data[:, 0] <= xorigin + buffer_length)[0]
150
+ data_send_down = MPI.send_down(data[cond])
151
+ cond = np.where(data[:, 0] >= xorigin + xboxsize - buffer_length)[0]
152
+ data_send_up = MPI.send_up(data[cond])
153
+ if MPI.rank == 0:
154
+ # data_send_up[:,0] -= xboxsize
155
+ datap = np.vstack([data, data_send_down])
156
+ elif MPI.rank == MPI.size - 1:
157
+ # data_send_down[:,0] += xboxsize
158
+ datap = np.vstack([data, data_send_up])
159
+ else:
160
+ datap = np.vstack([data, data_send_down, data_send_up])
161
+ return datap
162
+
163
+
164
+ def mpi_buffer_periodic_3D(
165
+ data: np.ndarray,
166
+ boxsize: Union[float, List[float]],
167
+ buffer_length: float,
168
+ MPI: object,
169
+ origin: Union[float, List[float]] = 0.0,
170
+ include_internal: bool = True,
171
+ ) -> np.ndarray:
172
+ """
173
+ Generates random buffer particles around a 3D box.
174
+
175
+ Parameters
176
+ ----------
177
+ data : array
178
+ Where columns 0, 1 and 2 correspond to the x, y and z coordinates.
179
+ xboxsize : float or list
180
+ Boxsize along x-axis.
181
+ buffer_length : float
182
+ Length of the buffer region.
183
+ MPI : class object
184
+ MPIutils MPI class object.
185
+ origin : float or list, optional
186
+ Origin point.
187
+ include_internal : bool, optional
188
+ Whether to include internal buffer particles.
189
+
190
+ Returns
191
+ -------
192
+ datap : array
193
+ Periodic data values.
194
+ """
195
+ if np.isscalar(origin):
196
+ xorigin, yorigin, zorigin = origin, origin, origin
197
+ else:
198
+ xorigin, yorigin, zorigin = origin[0], origin[1], origin[2]
199
+ if np.isscalar(boxsize):
200
+ xboxsize, yboxsize, zboxsize = boxsize, boxsize, boxsize
201
+ else:
202
+ xboxsize, yboxsize, zboxsize = boxsize[0], boxsize[1], boxsize[2]
203
+ datap = periodic.buffer_periodic(data, 1, yboxsize, buffer_length, origin=yorigin)
204
+ datap = periodic.buffer_periodic(datap, 2, zboxsize, buffer_length, origin=zorigin)
205
+ cond = np.where(datap[:, 0] <= xorigin + buffer_length)[0]
206
+ data_send_down = MPI.send_down(datap[cond])
207
+ cond = np.where(datap[:, 0] >= xorigin + xboxsize - buffer_length)[0]
208
+ data_send_up = MPI.send_up(datap[cond])
209
+ if MPI.rank == 0:
210
+ data_send_up[:, 0] -= xboxsize
211
+ elif MPI.rank == MPI.size - 1:
212
+ data_send_down[:, 0] += xboxsize
213
+ datap = np.vstack([datap, data_send_down, data_send_up])
214
+ if include_internal:
215
+ datap = mpi_buffer_internal_3D(datap, boxsize, buffer_length, MPI, origin)
216
+ return datap
@@ -0,0 +1,215 @@
1
+ import numpy as np
2
+
3
+ from .. import randoms
4
+
5
+
6
+ from typing import List, Tuple, Union
7
+
8
+
9
+ def mpi_buffer_random_2D(
10
+ npart: int,
11
+ boxsize: Union[float, List[float]],
12
+ limits: List[float],
13
+ buffer_length: float,
14
+ MPI: object,
15
+ ) -> Tuple[np.ndarray, np.ndarray]:
16
+ """
17
+ Generates random buffer particles around a 2D box.
18
+
19
+ Parameters
20
+ ----------
21
+ npart : int
22
+ Number of particles in the 2D box.
23
+ boxsize : float or list
24
+ Box size.
25
+ limits : list
26
+ Ranges for each coordinate axis [xmin, xmax, ymin, ymax].
27
+ buffer_length : float
28
+ Length of the buffer region.
29
+ MPI : class object
30
+ MPIutils MPI class object.
31
+
32
+ Returns
33
+ -------
34
+ x : array
35
+ Random x-values.
36
+ y : array
37
+ Random y-values.
38
+ """
39
+ if np.isscalar(boxsize):
40
+ xboxsize, yboxsize = boxsize, boxsize
41
+ else:
42
+ xboxsize, yboxsize = boxsize[0], boxsize[1]
43
+ # Determine number of particles needed in the padded region to maintain
44
+ # the average density.
45
+ part_dens = npart / (xboxsize * yboxsize)
46
+ # box edge 1
47
+ _xmin = limits[0] - buffer_length
48
+ _xmax = limits[1] + buffer_length
49
+ _ymin = limits[2] - buffer_length
50
+ _ymax = limits[2]
51
+ size1 = int(part_dens * (_xmax - _xmin) * (_ymax - _ymin))
52
+ x1, y1 = randoms.random_box(size1, _xmin, _xmax, _ymin, _ymax)
53
+ # box edge 2
54
+ _xmin = limits[0] - buffer_length
55
+ _xmax = limits[1] + buffer_length
56
+ _ymin = limits[3]
57
+ _ymax = limits[3] + buffer_length
58
+ size2 = int(part_dens * (_xmax - _xmin) * (_ymax - _ymin))
59
+ x2, y2 = randoms.random_box(size2, _xmin, _xmax, _ymin, _ymax)
60
+ x = np.concatenate([x1, x2])
61
+ y = np.concatenate([y1, y2])
62
+ if MPI.rank == 0:
63
+ _xmin = limits[0] - buffer_length
64
+ _xmax = limits[0]
65
+ _ymin = limits[2]
66
+ _ymax = limits[3]
67
+ size = int(part_dens * (_xmax - _xmin) * (_ymax - _ymin))
68
+ _x, _y = randoms.random_box(size, _xmin, _xmax, _ymin, _ymax)
69
+ x = np.concatenate([x, _x])
70
+ y = np.concatenate([y, _y])
71
+ if MPI.rank == MPI.size - 1:
72
+ _xmin = limits[1]
73
+ _xmax = limits[1] + buffer_length
74
+ _ymin = limits[2]
75
+ _ymax = limits[3]
76
+ size = int(part_dens * (_xmax - _xmin) * (_ymax - _ymin))
77
+ _x, _y = randoms.random_box(size, _xmin, _xmax, _ymin, _ymax)
78
+ x = np.concatenate([x, _x])
79
+ y = np.concatenate([y, _y])
80
+ return x, y
81
+
82
+
83
+ def mpi_buffer_random_3D(
84
+ npart: int,
85
+ boxsize: Union[float, List[float]],
86
+ limits: List[float],
87
+ buffer_length: float,
88
+ MPI: object,
89
+ ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
90
+ """
91
+ Generates random buffer particles around a 3D box.
92
+
93
+ Parameters
94
+ ----------
95
+ npart : int
96
+ Number of particles in the 3D box.
97
+ boxsize : float or list
98
+ Box size.
99
+ limits : list
100
+ Ranges for each coordinate axis [xmin, xmax, ymin, ymax, zmin, zmax].
101
+ buffer_length : float
102
+ Length of the buffer region.
103
+ MPI : class object
104
+ MPIutils MPI class object.
105
+
106
+ Returns
107
+ -------
108
+ x : array
109
+ Random x-values.
110
+ y : array
111
+ Random y-values.
112
+ z : array
113
+ Random z-values.
114
+ """
115
+ if np.isscalar(boxsize):
116
+ xboxsize, yboxsize, zboxsize = boxsize, boxsize, boxsize
117
+ else:
118
+ xboxsize, yboxsize, zboxsize = boxsize[0], boxsize[1], boxsize[2]
119
+ box_vol = xboxsize * yboxsize * zboxsize
120
+ part_dens = npart / box_vol
121
+ # Divide into three regions along z-axis
122
+ # Region 1: zrange = [-buffer_length, 0.]
123
+ # Region 2: zrange = [0., boxsize]
124
+ # Region 3: zrange = [boxsize, boxsize+buffer_length]
125
+ # Splitting region 2, into four regions.
126
+ # Subregion 21: xrange = [-buffer_length, boxsize], yrange = [-buffer_length, 0]
127
+ # Subregion 22: xrange = [boxsize, boxsize+buffer_length], yrange =[-buffer_length, boxsize]
128
+ # Subregion 23: xrange = [0, boxsize+buffer_length], yrange=[boxsize, boxsize+buffer_length]
129
+ # Subregion 24: xrange = [-buffer_length, 0], yrange = [0, boxsize+buffer_length]
130
+ # Region 1
131
+ xmin, xmax = limits[0] - buffer_length, limits[1] + buffer_length
132
+ ymin, ymax = limits[2] - buffer_length, limits[3] + buffer_length
133
+ zmin, zmax = limits[4] - buffer_length, limits[4]
134
+ npart1 = int(part_dens * (xmax - xmin) * (ymax - ymin) * (zmax - zmin))
135
+ x1, y1, z1 = randoms.random_cube(npart1, xmin, xmax, ymin, ymax, zmin, zmax)
136
+ # Region 3
137
+ xmin, xmax = limits[0] - buffer_length, limits[1] + buffer_length
138
+ ymin, ymax = limits[2] - buffer_length, limits[3] + buffer_length
139
+ zmin, zmax = limits[5], limits[5] + buffer_length
140
+ npart3 = int(part_dens * (xmax - xmin) * (ymax - ymin) * (zmax - zmin))
141
+ x3, y3, z3 = randoms.random_cube(npart3, xmin, xmax, ymin, ymax, zmin, zmax)
142
+ # x = np.concatenate([x1, x3])
143
+ # y = np.concatenate([y1, y3])
144
+ # z = np.concatenate([z1, z3])
145
+ # Subregion 21
146
+ xmin, xmax = limits[0] - buffer_length, limits[1] + buffer_length
147
+ ymin, ymax = limits[2] - buffer_length, limits[2]
148
+ zmin, zmax = limits[4], limits[5]
149
+ npart21 = int(part_dens * (xmax - xmin) * (ymax - ymin) * (zmax - zmin))
150
+ x21, y21, z21 = randoms.random_cube(npart21, xmin, xmax, ymin, ymax, zmin, zmax)
151
+ # Subregion 22
152
+ xmin, xmax = limits[0] - buffer_length, limits[1] + buffer_length
153
+ ymin, ymax = limits[3], limits[3] + buffer_length
154
+ zmin, zmax = limits[4], limits[5]
155
+ npart22 = int(part_dens * (xmax - xmin) * (ymax - ymin) * (zmax - zmin))
156
+ x22, y22, z22 = randoms.random_cube(npart22, xmin, xmax, ymin, ymax, zmin, zmax)
157
+ x = np.concatenate([x1, x21, x22, x3])
158
+ y = np.concatenate([y1, y21, y22, y3])
159
+ z = np.concatenate([z1, z21, z22, z3])
160
+ if MPI.rank == 0:
161
+ # Subregion 23
162
+ xmin, xmax = limits[0] - buffer_length, limits[0]
163
+ ymin, ymax = limits[2], limits[3]
164
+ zmin, zmax = limits[4], limits[5]
165
+ npart23 = int(part_dens * (xmax - xmin) * (ymax - ymin) * (zmax - zmin))
166
+ x23, y23, z23 = randoms.random_cube(npart23, xmin, xmax, ymin, ymax, zmin, zmax)
167
+ x = np.concatenate([x, x23])
168
+ y = np.concatenate([y, y23])
169
+ z = np.concatenate([z, z23])
170
+ elif MPI.rank == MPI.size - 1:
171
+ # Subregion 24
172
+ xmin, xmax = limits[1], limits[1] + buffer_length
173
+ ymin, ymax = limits[2], limits[3]
174
+ zmin, zmax = limits[4], limits[5]
175
+ npart24 = int(part_dens * (xmax - xmin) * (ymax - ymin) * (zmax - zmin))
176
+ x24, y24, z24 = randoms.random_cube(npart24, xmin, xmax, ymin, ymax, zmin, zmax)
177
+ x = np.concatenate([x, x24])
178
+ y = np.concatenate([y, y24])
179
+ z = np.concatenate([z, z24])
180
+ return x, y, z
181
+
182
+
183
+ def mpi_buffer_random_utils(
184
+ data: np.ndarray, limits: List[float], buffer_length: float, MPI: object
185
+ ) -> np.ndarray:
186
+ """
187
+ Generates random buffer particles around a 2D box.
188
+
189
+ Parameters
190
+ ----------
191
+ data : array
192
+ Where columns 0 and 1 are x and y.
193
+ limits : list
194
+ Ranges for each coordinate axis [xmin, xmax, ymin, ymax].
195
+ buffer_length : float
196
+ Length of the buffer region.
197
+ MPI : class object
198
+ MPIutils MPI class object.
199
+
200
+ Returns
201
+ -------
202
+ datap : array
203
+ Periodic data values.
204
+ """
205
+ cond = np.where(data[:, 0] <= limits[0] + buffer_length)[0]
206
+ data_send_down = MPI.send_down(data[cond])
207
+ cond = np.where(data[:, 0] >= limits[1] - buffer_length)[0]
208
+ data_send_up = MPI.send_up(data[cond])
209
+ if MPI.rank == 0:
210
+ datap = np.vstack([data, data_send_down])
211
+ elif MPI.rank == MPI.size - 1:
212
+ datap = np.vstack([data, data_send_up])
213
+ else:
214
+ datap = np.vstack([data, data_send_down, data_send_up])
215
+ return datap