lsurf 1.0.0__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 (180) hide show
  1. lsurf/__init__.py +471 -0
  2. lsurf/analysis/__init__.py +107 -0
  3. lsurf/analysis/healpix_utils.py +418 -0
  4. lsurf/analysis/sphere_viz.py +1280 -0
  5. lsurf/cli/__init__.py +48 -0
  6. lsurf/cli/build.py +398 -0
  7. lsurf/cli/config_schema.py +318 -0
  8. lsurf/cli/gui_cmd.py +76 -0
  9. lsurf/cli/interactive.py +850 -0
  10. lsurf/cli/main.py +81 -0
  11. lsurf/cli/run.py +806 -0
  12. lsurf/detectors/__init__.py +266 -0
  13. lsurf/detectors/analysis.py +289 -0
  14. lsurf/detectors/base.py +284 -0
  15. lsurf/detectors/constant_size_rings.py +485 -0
  16. lsurf/detectors/directional.py +45 -0
  17. lsurf/detectors/extended/__init__.py +73 -0
  18. lsurf/detectors/extended/local_sphere.py +353 -0
  19. lsurf/detectors/extended/recording_sphere.py +368 -0
  20. lsurf/detectors/planar.py +45 -0
  21. lsurf/detectors/protocol.py +187 -0
  22. lsurf/detectors/recording_spheres.py +63 -0
  23. lsurf/detectors/results.py +1140 -0
  24. lsurf/detectors/small/__init__.py +79 -0
  25. lsurf/detectors/small/directional.py +330 -0
  26. lsurf/detectors/small/planar.py +401 -0
  27. lsurf/detectors/small/spherical.py +450 -0
  28. lsurf/detectors/spherical.py +45 -0
  29. lsurf/geometry/__init__.py +199 -0
  30. lsurf/geometry/builder.py +478 -0
  31. lsurf/geometry/cell.py +228 -0
  32. lsurf/geometry/cell_geometry.py +247 -0
  33. lsurf/geometry/detector_arrays.py +1785 -0
  34. lsurf/geometry/geometry.py +222 -0
  35. lsurf/geometry/surface_analysis.py +375 -0
  36. lsurf/geometry/validation.py +91 -0
  37. lsurf/gui/__init__.py +51 -0
  38. lsurf/gui/app.py +903 -0
  39. lsurf/gui/core/__init__.py +39 -0
  40. lsurf/gui/core/scene.py +343 -0
  41. lsurf/gui/core/simulation.py +264 -0
  42. lsurf/gui/renderers/__init__.py +40 -0
  43. lsurf/gui/renderers/ray_renderer.py +353 -0
  44. lsurf/gui/renderers/source_renderer.py +505 -0
  45. lsurf/gui/renderers/surface_renderer.py +477 -0
  46. lsurf/gui/views/__init__.py +48 -0
  47. lsurf/gui/views/config_editor.py +3199 -0
  48. lsurf/gui/views/properties.py +257 -0
  49. lsurf/gui/views/results.py +291 -0
  50. lsurf/gui/views/scene_tree.py +180 -0
  51. lsurf/gui/views/viewport_3d.py +555 -0
  52. lsurf/gui/views/visualizations.py +712 -0
  53. lsurf/materials/__init__.py +169 -0
  54. lsurf/materials/base/__init__.py +64 -0
  55. lsurf/materials/base/full_inhomogeneous.py +208 -0
  56. lsurf/materials/base/grid_inhomogeneous.py +319 -0
  57. lsurf/materials/base/homogeneous.py +342 -0
  58. lsurf/materials/base/material_field.py +527 -0
  59. lsurf/materials/base/simple_inhomogeneous.py +418 -0
  60. lsurf/materials/base/spectral_inhomogeneous.py +497 -0
  61. lsurf/materials/implementations/__init__.py +120 -0
  62. lsurf/materials/implementations/data/alpha_values_typical_atmosphere_updated.txt +24 -0
  63. lsurf/materials/implementations/duct_atmosphere.py +390 -0
  64. lsurf/materials/implementations/exponential_atmosphere.py +435 -0
  65. lsurf/materials/implementations/gaussian_lens.py +120 -0
  66. lsurf/materials/implementations/interpolated_data.py +123 -0
  67. lsurf/materials/implementations/layered_atmosphere.py +134 -0
  68. lsurf/materials/implementations/linear_gradient.py +109 -0
  69. lsurf/materials/implementations/linsley_atmosphere.py +764 -0
  70. lsurf/materials/implementations/standard_materials.py +126 -0
  71. lsurf/materials/implementations/turbulent_atmosphere.py +135 -0
  72. lsurf/materials/implementations/us_standard_atmosphere.py +149 -0
  73. lsurf/materials/utils/__init__.py +77 -0
  74. lsurf/materials/utils/constants.py +45 -0
  75. lsurf/materials/utils/device_functions.py +117 -0
  76. lsurf/materials/utils/dispersion.py +160 -0
  77. lsurf/materials/utils/factories.py +142 -0
  78. lsurf/propagation/__init__.py +91 -0
  79. lsurf/propagation/detector_gpu.py +67 -0
  80. lsurf/propagation/gpu_device_rays.py +294 -0
  81. lsurf/propagation/kernels/__init__.py +175 -0
  82. lsurf/propagation/kernels/absorption/__init__.py +61 -0
  83. lsurf/propagation/kernels/absorption/grid.py +240 -0
  84. lsurf/propagation/kernels/absorption/simple.py +232 -0
  85. lsurf/propagation/kernels/absorption/spectral.py +410 -0
  86. lsurf/propagation/kernels/detection/__init__.py +64 -0
  87. lsurf/propagation/kernels/detection/protocol.py +102 -0
  88. lsurf/propagation/kernels/detection/spherical.py +255 -0
  89. lsurf/propagation/kernels/device_functions.py +790 -0
  90. lsurf/propagation/kernels/fresnel/__init__.py +64 -0
  91. lsurf/propagation/kernels/fresnel/protocol.py +97 -0
  92. lsurf/propagation/kernels/fresnel/standard.py +258 -0
  93. lsurf/propagation/kernels/intersection/__init__.py +79 -0
  94. lsurf/propagation/kernels/intersection/annular_plane.py +207 -0
  95. lsurf/propagation/kernels/intersection/bounded_plane.py +205 -0
  96. lsurf/propagation/kernels/intersection/plane.py +166 -0
  97. lsurf/propagation/kernels/intersection/protocol.py +95 -0
  98. lsurf/propagation/kernels/intersection/signed_distance.py +742 -0
  99. lsurf/propagation/kernels/intersection/sphere.py +190 -0
  100. lsurf/propagation/kernels/propagation/__init__.py +85 -0
  101. lsurf/propagation/kernels/propagation/grid.py +527 -0
  102. lsurf/propagation/kernels/propagation/protocol.py +105 -0
  103. lsurf/propagation/kernels/propagation/simple.py +460 -0
  104. lsurf/propagation/kernels/propagation/spectral.py +875 -0
  105. lsurf/propagation/kernels/registry.py +331 -0
  106. lsurf/propagation/kernels/surface/__init__.py +72 -0
  107. lsurf/propagation/kernels/surface/bisection.py +232 -0
  108. lsurf/propagation/kernels/surface/detection.py +402 -0
  109. lsurf/propagation/kernels/surface/reduction.py +166 -0
  110. lsurf/propagation/propagator_protocol.py +222 -0
  111. lsurf/propagation/propagators/__init__.py +101 -0
  112. lsurf/propagation/propagators/detector_handler.py +354 -0
  113. lsurf/propagation/propagators/factory.py +200 -0
  114. lsurf/propagation/propagators/fresnel_handler.py +305 -0
  115. lsurf/propagation/propagators/gpu_gradient.py +566 -0
  116. lsurf/propagation/propagators/gpu_surface_propagator.py +707 -0
  117. lsurf/propagation/propagators/gradient.py +429 -0
  118. lsurf/propagation/propagators/intersection_handler.py +327 -0
  119. lsurf/propagation/propagators/material_propagator.py +398 -0
  120. lsurf/propagation/propagators/signed_distance_handler.py +522 -0
  121. lsurf/propagation/propagators/spectral_gpu_gradient.py +553 -0
  122. lsurf/propagation/propagators/surface_interaction.py +616 -0
  123. lsurf/propagation/propagators/surface_propagator.py +719 -0
  124. lsurf/py.typed +1 -0
  125. lsurf/simulation/__init__.py +70 -0
  126. lsurf/simulation/config.py +164 -0
  127. lsurf/simulation/orchestrator.py +462 -0
  128. lsurf/simulation/result.py +299 -0
  129. lsurf/simulation/simulation.py +262 -0
  130. lsurf/sources/__init__.py +128 -0
  131. lsurf/sources/base.py +264 -0
  132. lsurf/sources/collimated.py +252 -0
  133. lsurf/sources/custom.py +409 -0
  134. lsurf/sources/diverging.py +228 -0
  135. lsurf/sources/gaussian.py +272 -0
  136. lsurf/sources/parallel_from_positions.py +197 -0
  137. lsurf/sources/point.py +172 -0
  138. lsurf/sources/uniform_diverging.py +258 -0
  139. lsurf/surfaces/__init__.py +184 -0
  140. lsurf/surfaces/cpu/__init__.py +50 -0
  141. lsurf/surfaces/cpu/curved_wave.py +463 -0
  142. lsurf/surfaces/cpu/gerstner_wave.py +381 -0
  143. lsurf/surfaces/cpu/wave_params.py +118 -0
  144. lsurf/surfaces/gpu/__init__.py +72 -0
  145. lsurf/surfaces/gpu/annular_plane.py +453 -0
  146. lsurf/surfaces/gpu/bounded_plane.py +390 -0
  147. lsurf/surfaces/gpu/curved_wave.py +483 -0
  148. lsurf/surfaces/gpu/gerstner_wave.py +377 -0
  149. lsurf/surfaces/gpu/multi_curved_wave.py +520 -0
  150. lsurf/surfaces/gpu/plane.py +299 -0
  151. lsurf/surfaces/gpu/recording_sphere.py +587 -0
  152. lsurf/surfaces/gpu/sphere.py +311 -0
  153. lsurf/surfaces/protocol.py +336 -0
  154. lsurf/surfaces/registry.py +373 -0
  155. lsurf/utilities/__init__.py +175 -0
  156. lsurf/utilities/detector_analysis.py +814 -0
  157. lsurf/utilities/fresnel.py +628 -0
  158. lsurf/utilities/interactions.py +1215 -0
  159. lsurf/utilities/propagation.py +602 -0
  160. lsurf/utilities/ray_data.py +532 -0
  161. lsurf/utilities/recording_sphere.py +745 -0
  162. lsurf/utilities/time_spread.py +463 -0
  163. lsurf/visualization/__init__.py +329 -0
  164. lsurf/visualization/absorption_plots.py +334 -0
  165. lsurf/visualization/atmospheric_plots.py +754 -0
  166. lsurf/visualization/common.py +348 -0
  167. lsurf/visualization/detector_plots.py +1350 -0
  168. lsurf/visualization/detector_sphere_plots.py +1173 -0
  169. lsurf/visualization/fresnel_plots.py +1061 -0
  170. lsurf/visualization/ocean_simulation_plots.py +999 -0
  171. lsurf/visualization/polarization_plots.py +916 -0
  172. lsurf/visualization/raytracing_plots.py +1521 -0
  173. lsurf/visualization/ring_detector_plots.py +1867 -0
  174. lsurf/visualization/time_spread_plots.py +531 -0
  175. lsurf-1.0.0.dist-info/METADATA +381 -0
  176. lsurf-1.0.0.dist-info/RECORD +180 -0
  177. lsurf-1.0.0.dist-info/WHEEL +5 -0
  178. lsurf-1.0.0.dist-info/entry_points.txt +2 -0
  179. lsurf-1.0.0.dist-info/licenses/LICENSE +32 -0
  180. lsurf-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,294 @@
1
+ # The Clear BSD License
2
+ #
3
+ # Copyright (c) 2026 Tobias Heibges
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted (subject to the limitations in the disclaimer
8
+ # below) provided that the following conditions are met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ #
13
+ # * Redistributions in binary form must reproduce the above copyright
14
+ # notice, this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ #
17
+ # * Neither the name of the copyright holder nor the names of its
18
+ # contributors may be used to endorse or promote products derived from this
19
+ # software without specific prior written permission.
20
+ #
21
+ # NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
22
+ # THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23
+ # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
30
+ # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+
34
+ """
35
+ GPU Device Rays - Unified GPU Ray Data Structure
36
+
37
+ Provides a single data class holding device arrays for ALL GPU operations.
38
+ Both material propagation kernels and surface detection kernels operate on
39
+ these same device arrays - no duplication.
40
+
41
+ This minimizes CPU-GPU transfers by keeping ray data GPU-resident throughout
42
+ the entire propagation loop.
43
+
44
+ Memory Layout
45
+ -------------
46
+ GPUDeviceRays contains:
47
+ - Core ray state (positions, directions, active, paths) - used by propagation
48
+ - Surface detection state (prev_positions, signed_dist, crossings) - used by detection
49
+ - Reduction output (tiny, single copy per step for loop termination)
50
+
51
+ Usage
52
+ -----
53
+ # One-time upload at start
54
+ gpu_rays = GPUDeviceRays.from_ray_batch(rays, num_surfaces)
55
+
56
+ # GPU-resident loop
57
+ for step in range(max_steps):
58
+ # Kernels operate on same device arrays
59
+ propagation_kernel[...](gpu_rays.d_positions, gpu_rays.d_directions, ...)
60
+ detection_kernel[...](gpu_rays.d_positions, gpu_rays.d_prev_signed_dist, ...)
61
+
62
+ # One-time download at end
63
+ gpu_rays.to_ray_batch(rays)
64
+ """
65
+
66
+ from dataclasses import dataclass
67
+ from typing import TYPE_CHECKING
68
+
69
+ import numpy as np
70
+ import numpy.typing as npt
71
+
72
+ # GPU support is optional
73
+ try:
74
+ from numba import cuda
75
+
76
+ HAS_CUDA = cuda.is_available()
77
+ except ImportError:
78
+ HAS_CUDA = False
79
+
80
+ class _FakeCuda:
81
+ @staticmethod
82
+ def is_available():
83
+ return False
84
+
85
+ @staticmethod
86
+ def to_device(arr):
87
+ return arr
88
+
89
+ @staticmethod
90
+ def device_array(shape, dtype=np.float32):
91
+ return np.zeros(shape, dtype=dtype)
92
+
93
+ @staticmethod
94
+ def synchronize():
95
+ pass
96
+
97
+ cuda = _FakeCuda() # type: ignore[assignment]
98
+
99
+
100
+ if TYPE_CHECKING:
101
+ from ..utilities.ray_data import RayBatch
102
+
103
+
104
+ @dataclass
105
+ class GPUDeviceRays:
106
+ """
107
+ Unified GPU ray storage shared by propagation and surface detection.
108
+
109
+ Both GPUGradientPropagator kernels and surface detection kernels
110
+ operate on these same device arrays - no duplication.
111
+
112
+ Attributes
113
+ ----------
114
+ d_positions : device array, shape (N, 3)
115
+ Ray positions (float32)
116
+ d_directions : device array, shape (N, 3)
117
+ Ray directions (float32)
118
+ d_active : device array, shape (N,)
119
+ Active mask (bool)
120
+ d_geo_path : device array, shape (N,)
121
+ Geometric path lengths (float32)
122
+ d_opt_path : device array, shape (N,)
123
+ Optical path lengths (float32)
124
+ d_acc_time : device array, shape (N,)
125
+ Accumulated time (float32)
126
+ d_wavelengths : device array, shape (N,)
127
+ Ray wavelengths (float32)
128
+ d_intensities : device array, shape (N,)
129
+ Ray intensities (float32)
130
+ d_optical_depth : device array, shape (N,)
131
+ Accumulated optical depth τ = ∫α·ds (float32)
132
+ d_prev_positions : device array, shape (N, 3)
133
+ Previous positions for bisection (float32)
134
+ d_prev_signed_dist : device array, shape (N, S)
135
+ Previous signed distances per surface (float32)
136
+ d_hit_surface_idx : device array, shape (N,)
137
+ Surface index for each hit (-1 = no hit) (int32)
138
+ d_hit_positions : device array, shape (N, 3)
139
+ Hit positions (float32)
140
+ d_crossing_mask : device array, shape (N,)
141
+ Rays that crossed a surface this step (bool)
142
+ d_reduction_result : device array, shape (2,)
143
+ [num_active, num_crossing] for loop termination (int32)
144
+ num_rays : int
145
+ Total number of rays
146
+ num_surfaces : int
147
+ Number of surfaces being tracked
148
+ """
149
+
150
+ d_positions: npt.NDArray
151
+ d_directions: npt.NDArray
152
+ d_active: npt.NDArray
153
+ d_geo_path: npt.NDArray
154
+ d_opt_path: npt.NDArray
155
+ d_acc_time: npt.NDArray
156
+ d_wavelengths: npt.NDArray
157
+ d_intensities: npt.NDArray
158
+ d_optical_depth: npt.NDArray
159
+ d_prev_positions: npt.NDArray
160
+ d_prev_signed_dist: npt.NDArray
161
+ d_hit_surface_idx: npt.NDArray
162
+ d_hit_positions: npt.NDArray
163
+ d_crossing_mask: npt.NDArray
164
+ d_reduction_result: npt.NDArray
165
+ num_rays: int
166
+ num_surfaces: int
167
+
168
+ @classmethod
169
+ def from_ray_batch(
170
+ cls,
171
+ rays: "RayBatch",
172
+ num_surfaces: int,
173
+ ) -> "GPUDeviceRays":
174
+ """
175
+ Upload RayBatch to GPU (one-time at start).
176
+
177
+ Parameters
178
+ ----------
179
+ rays : RayBatch
180
+ Source ray batch to upload
181
+ num_surfaces : int
182
+ Number of surfaces to track for detection
183
+
184
+ Returns
185
+ -------
186
+ GPUDeviceRays
187
+ GPU-resident ray data
188
+ """
189
+ n = rays.num_rays
190
+
191
+ # Initialize optical depth from rays if present, otherwise zeros
192
+ if rays.optical_depth is not None:
193
+ optical_depth_arr = cuda.to_device(rays.optical_depth.astype(np.float32))
194
+ else:
195
+ optical_depth_arr = cuda.to_device(np.zeros(n, dtype=np.float32))
196
+
197
+ return cls(
198
+ d_positions=cuda.to_device(rays.positions.astype(np.float32)),
199
+ d_directions=cuda.to_device(rays.directions.astype(np.float32)),
200
+ d_active=cuda.to_device(rays.active.astype(np.bool_)),
201
+ d_geo_path=cuda.to_device(rays.geometric_path_lengths.astype(np.float32)),
202
+ d_opt_path=cuda.to_device(rays.optical_path_lengths.astype(np.float32)),
203
+ d_acc_time=cuda.to_device(rays.accumulated_time.astype(np.float32)),
204
+ d_wavelengths=cuda.to_device(rays.wavelengths.astype(np.float32)),
205
+ d_intensities=cuda.to_device(rays.intensities.astype(np.float32)),
206
+ d_optical_depth=optical_depth_arr,
207
+ d_prev_positions=cuda.device_array((n, 3), dtype=np.float32),
208
+ d_prev_signed_dist=cuda.device_array((n, num_surfaces), dtype=np.float32),
209
+ d_hit_surface_idx=cuda.to_device(np.full(n, -1, dtype=np.int32)),
210
+ d_hit_positions=cuda.device_array((n, 3), dtype=np.float32),
211
+ d_crossing_mask=cuda.device_array(n, dtype=np.bool_),
212
+ d_reduction_result=cuda.device_array(2, dtype=np.int32),
213
+ num_rays=n,
214
+ num_surfaces=num_surfaces,
215
+ )
216
+
217
+ def to_ray_batch(self, rays: "RayBatch") -> None:
218
+ """
219
+ Download final state back to RayBatch (one-time at end).
220
+
221
+ Parameters
222
+ ----------
223
+ rays : RayBatch
224
+ Target ray batch to update in-place
225
+ """
226
+ if HAS_CUDA:
227
+ cuda.synchronize()
228
+
229
+ rays.positions[:] = self.d_positions.copy_to_host()
230
+ rays.directions[:] = self.d_directions.copy_to_host()
231
+ rays.active[:] = self.d_active.copy_to_host()
232
+ rays.geometric_path_lengths[:] = self.d_geo_path.copy_to_host()
233
+ rays.optical_path_lengths[:] = self.d_opt_path.copy_to_host()
234
+ rays.accumulated_time[:] = self.d_acc_time.copy_to_host()
235
+ rays.intensities[:] = self.d_intensities.copy_to_host()
236
+ if rays.optical_depth is not None:
237
+ rays.optical_depth[:] = self.d_optical_depth.copy_to_host()
238
+
239
+ def get_hit_data(self) -> tuple[npt.NDArray, npt.NDArray, npt.NDArray]:
240
+ """
241
+ Download hit data from GPU.
242
+
243
+ Returns
244
+ -------
245
+ hit_surface_idx : ndarray, shape (N,)
246
+ Surface index for each hit (-1 = no hit)
247
+ hit_positions : ndarray, shape (N, 3)
248
+ Hit positions
249
+ hit_mask : ndarray, shape (N,)
250
+ True for rays that hit any surface
251
+ """
252
+ if HAS_CUDA:
253
+ cuda.synchronize()
254
+
255
+ hit_surface_idx = self.d_hit_surface_idx.copy_to_host()
256
+ hit_positions = self.d_hit_positions.copy_to_host()
257
+ hit_mask = hit_surface_idx >= 0
258
+
259
+ return hit_surface_idx, hit_positions, hit_mask
260
+
261
+ def reset_crossing_state(self) -> None:
262
+ """
263
+ Reset crossing detection state for next iteration.
264
+
265
+ Called at the start of each propagation step to clear
266
+ the crossing mask and reset reduction counters.
267
+ """
268
+ # Reset crossing mask to False
269
+ zeros_bool = np.zeros(self.num_rays, dtype=np.bool_)
270
+ self.d_crossing_mask.copy_to_device(zeros_bool)
271
+
272
+ # Reset reduction result
273
+ zeros_int = np.zeros(2, dtype=np.int32)
274
+ self.d_reduction_result.copy_to_device(zeros_int)
275
+
276
+ def get_reduction_result(self) -> tuple[int, int]:
277
+ """
278
+ Download reduction result (small transfer).
279
+
280
+ Returns
281
+ -------
282
+ num_active : int
283
+ Number of active rays
284
+ num_crossing : int
285
+ Number of rays that crossed a surface
286
+ """
287
+ if HAS_CUDA:
288
+ cuda.synchronize()
289
+
290
+ result = self.d_reduction_result.copy_to_host()
291
+ return int(result[0]), int(result[1])
292
+
293
+
294
+ __all__ = ["GPUDeviceRays", "HAS_CUDA"]
@@ -0,0 +1,175 @@
1
+ # The Clear BSD License
2
+ #
3
+ # Copyright (c) 2026 Tobias Heibges
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted (subject to the limitations in the disclaimer
8
+ # below) provided that the following conditions are met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ #
13
+ # * Redistributions in binary form must reproduce the above copyright
14
+ # notice, this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ #
17
+ # * Neither the name of the copyright holder nor the names of its
18
+ # contributors may be used to endorse or promote products derived from this
19
+ # software without specific prior written permission.
20
+ #
21
+ # NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
22
+ # THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23
+ # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
30
+ # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+
34
+ """
35
+ GPU Kernels for Ray Tracing
36
+
37
+ This package contains all CUDA kernels organized by function:
38
+
39
+ - propagation/: Material propagation kernels (simple, spectral, grid)
40
+ - intersection/: Surface intersection kernels (plane, sphere, signed distance)
41
+ - fresnel/: Fresnel reflection/refraction kernels
42
+ - detection/: Ray detection kernels (spherical)
43
+ - device_functions: Shared device functions (integration, dispersion)
44
+ - registry: Kernel ID enums and registration system
45
+
46
+ All kernels support optional CUDA - they gracefully fall back to
47
+ no-op decorators when numba.cuda is not available.
48
+
49
+ Kernel Types
50
+ ------------
51
+ - PropagationKernelID: Material propagation (SIMPLE_*, SPECTRAL_*, GRID_*)
52
+ - IntersectionKernelID: Surface intersection (PLANE_*, SPHERE_*, SIGNED_DISTANCE_*, SURFACE_NORMAL_*)
53
+ - DetectionKernelID: Ray detection (SPHERICAL_*, PLANAR_*)
54
+ - FresnelKernelID: Fresnel equations (STANDARD, POLARIZED)
55
+ """
56
+
57
+ # Re-export kernel registry (enums and registration)
58
+ from .registry import (
59
+ PropagationKernelID,
60
+ IntersectionKernelID,
61
+ DetectionKernelID,
62
+ FresnelKernelID,
63
+ PropagatorID,
64
+ KernelID,
65
+ register_kernel,
66
+ get_kernel,
67
+ get_registered_kernels,
68
+ list_kernels,
69
+ )
70
+
71
+ # Re-export protocols
72
+ from .propagation.protocol import PropagationKernelProtocol
73
+ from .intersection.protocol import IntersectionKernelProtocol
74
+ from .fresnel.protocol import FresnelKernelProtocol
75
+ from .detection.protocol import DetectionKernelProtocol
76
+
77
+ # Re-export device functions
78
+ from .device_functions import (
79
+ device_euler_step,
80
+ device_rk4_step,
81
+ device_adaptive_step_size,
82
+ device_sellmeier_equation,
83
+ device_cauchy_equation,
84
+ euler_step,
85
+ rk4_step,
86
+ compute_adaptive_step_size,
87
+ normalize_directions,
88
+ euler_step_batch,
89
+ rk4_step_batch,
90
+ HAS_CUDA,
91
+ )
92
+
93
+ # Re-export propagation kernels
94
+ from .propagation import (
95
+ _kernel_simple_inhomogeneous_euler,
96
+ _kernel_simple_inhomogeneous_rk4,
97
+ _kernel_spectral_inhomogeneous_euler,
98
+ _kernel_spectral_inhomogeneous_rk4,
99
+ _kernel_spectral_inhomogeneous_euler_perray,
100
+ _kernel_spectral_inhomogeneous_rk4_perray,
101
+ _kernel_grid_inhomogeneous_euler,
102
+ _kernel_grid_inhomogeneous_rk4,
103
+ )
104
+
105
+ # Re-export intersection kernels (pure CUDA only)
106
+ from .intersection import (
107
+ kernel_plane_intersect,
108
+ kernel_sphere_intersect,
109
+ kernel_signed_distance,
110
+ kernel_surface_normal,
111
+ )
112
+
113
+ # Re-export fresnel kernels (pure CUDA only)
114
+ from .fresnel import (
115
+ kernel_fresnel_standard,
116
+ kernel_fresnel_polarized,
117
+ )
118
+
119
+ # Re-export detection kernels (pure CUDA only)
120
+ from .detection import (
121
+ kernel_spherical_detect_single,
122
+ kernel_spherical_detect_multi,
123
+ )
124
+
125
+ __all__ = [
126
+ # Kernel registry
127
+ "PropagationKernelID",
128
+ "IntersectionKernelID",
129
+ "DetectionKernelID",
130
+ "FresnelKernelID",
131
+ "PropagatorID",
132
+ "KernelID",
133
+ "register_kernel",
134
+ "get_kernel",
135
+ "get_registered_kernels",
136
+ "list_kernels",
137
+ # Protocols
138
+ "PropagationKernelProtocol",
139
+ "IntersectionKernelProtocol",
140
+ "FresnelKernelProtocol",
141
+ "DetectionKernelProtocol",
142
+ # Device functions
143
+ "device_euler_step",
144
+ "device_rk4_step",
145
+ "device_adaptive_step_size",
146
+ "device_sellmeier_equation",
147
+ "device_cauchy_equation",
148
+ "euler_step",
149
+ "rk4_step",
150
+ "compute_adaptive_step_size",
151
+ "normalize_directions",
152
+ "euler_step_batch",
153
+ "rk4_step_batch",
154
+ "HAS_CUDA",
155
+ # Propagation kernels
156
+ "_kernel_simple_inhomogeneous_euler",
157
+ "_kernel_simple_inhomogeneous_rk4",
158
+ "_kernel_spectral_inhomogeneous_euler",
159
+ "_kernel_spectral_inhomogeneous_rk4",
160
+ "_kernel_spectral_inhomogeneous_euler_perray",
161
+ "_kernel_spectral_inhomogeneous_rk4_perray",
162
+ "_kernel_grid_inhomogeneous_euler",
163
+ "_kernel_grid_inhomogeneous_rk4",
164
+ # Intersection kernels (pure CUDA only)
165
+ "kernel_plane_intersect",
166
+ "kernel_sphere_intersect",
167
+ "kernel_signed_distance",
168
+ "kernel_surface_normal",
169
+ # Fresnel kernels (pure CUDA only)
170
+ "kernel_fresnel_standard",
171
+ "kernel_fresnel_polarized",
172
+ # Detection kernels (pure CUDA only)
173
+ "kernel_spherical_detect_single",
174
+ "kernel_spherical_detect_multi",
175
+ ]
@@ -0,0 +1,61 @@
1
+ # The Clear BSD License
2
+ #
3
+ # Copyright (c) 2026 Tobias Heibges
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted (subject to the limitations in the disclaimer
8
+ # below) provided that the following conditions are met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ #
13
+ # * Redistributions in binary form must reproduce the above copyright
14
+ # notice, this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ #
17
+ # * Neither the name of the copyright holder nor the names of its
18
+ # contributors may be used to endorse or promote products derived from this
19
+ # software without specific prior written permission.
20
+ #
21
+ # NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
22
+ # THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23
+ # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
30
+ # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+
34
+ """
35
+ Absorption Kernels
36
+
37
+ GPU kernels for applying Beer-Lambert absorption after propagation.
38
+ These kernels are separate from propagation kernels to maintain modularity.
39
+
40
+ The kernels update:
41
+ - intensities: I *= exp(-α·ds) for each step
42
+ - optical_depth: τ += α·ds (accumulated optical depth)
43
+ """
44
+
45
+ from .simple import (
46
+ _kernel_absorption_simple,
47
+ )
48
+ from .spectral import (
49
+ _kernel_absorption_spectral,
50
+ _kernel_absorption_spectral_perray,
51
+ )
52
+ from .grid import (
53
+ _kernel_absorption_grid,
54
+ )
55
+
56
+ __all__ = [
57
+ "_kernel_absorption_simple",
58
+ "_kernel_absorption_spectral",
59
+ "_kernel_absorption_spectral_perray",
60
+ "_kernel_absorption_grid",
61
+ ]