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,169 @@
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
+ Materials Module
36
+
37
+ Provides optical material definitions with spatially-varying properties.
38
+ Supports homogeneous materials with constant properties and dispersion models.
39
+
40
+ Module Structure
41
+ ----------------
42
+ - base/: Abstract base classes (MaterialField, HomogeneousMaterial, etc.)
43
+ - implementations/: Concrete material implementations
44
+ - utils/: Dispersion functions, factories, constants
45
+
46
+ Note: GPU propagation kernels are in lsurf.propagation.kernels.propagation
47
+
48
+ Classes
49
+ -------
50
+ MaterialField
51
+ Abstract base class for material property fields.
52
+ HomogeneousMaterial
53
+ Uniform material with constant optical properties.
54
+ SimpleInhomogeneousModel
55
+ Radially-symmetric inhomogeneous materials (GPU via LUT).
56
+ GridInhomogeneousModel
57
+ 3D grid-based inhomogeneous materials (GPU via trilinear interp).
58
+ FullInhomogeneousModel
59
+ Arbitrary Python inhomogeneous materials (CPU-only).
60
+
61
+ Constants
62
+ ---------
63
+ VACUUM
64
+ Perfect vacuum with n = 1.0.
65
+ AIR_STP
66
+ Air at standard temperature and pressure, n = 1.000293.
67
+ WATER
68
+ Pure water with n = 1.333 and absorption.
69
+ BK7_GLASS
70
+ Schott N-BK7 optical glass, n = 1.5168.
71
+
72
+ Functions
73
+ ---------
74
+ sellmeier_refractive_index
75
+ Compute n using Sellmeier equation.
76
+ cauchy_refractive_index
77
+ Compute n using Cauchy equation.
78
+ create_sellmeier_material
79
+ Factory for Sellmeier-dispersion materials.
80
+ create_cauchy_material
81
+ Factory for Cauchy-dispersion materials.
82
+
83
+ Examples
84
+ --------
85
+ >>> from lsurf.materials import VACUUM, WATER, HomogeneousMaterial
86
+ >>>
87
+ >>> # Use pre-defined material
88
+ >>> n = WATER.get_refractive_index(0, 0, 0, 550e-9)
89
+ >>>
90
+ >>> # Create custom material
91
+ >>> oil = HomogeneousMaterial("Oil", 1.47, absorption_coef=0.01)
92
+ """
93
+
94
+ # Base classes
95
+ from .base import (
96
+ MaterialField,
97
+ HomogeneousMaterial,
98
+ SimpleInhomogeneousModel,
99
+ GridInhomogeneousModel,
100
+ FullInhomogeneousModel,
101
+ EARTH_RADIUS,
102
+ )
103
+
104
+ # Standard material constants
105
+ from .implementations import (
106
+ VACUUM,
107
+ AIR_STP,
108
+ WATER,
109
+ BK7_GLASS,
110
+ )
111
+
112
+ # Atmosphere implementations
113
+ from .implementations import (
114
+ ExponentialAtmosphere,
115
+ STANDARD_ATMOSPHERE,
116
+ create_exponential_atmosphere,
117
+ DuctAtmosphere,
118
+ create_duct_atmosphere,
119
+ )
120
+
121
+ # Utilities
122
+ from .utils import (
123
+ # Constants
124
+ N_SEA_LEVEL,
125
+ SCALE_HEIGHT_DEFAULT,
126
+ # Dispersion functions
127
+ sellmeier_refractive_index,
128
+ cauchy_refractive_index,
129
+ # Factory functions
130
+ create_sellmeier_material,
131
+ create_cauchy_material,
132
+ # GPU device functions
133
+ device_sellmeier_equation,
134
+ device_cauchy_equation,
135
+ )
136
+
137
+ __all__ = [
138
+ # Base classes
139
+ "MaterialField",
140
+ "HomogeneousMaterial",
141
+ # Inhomogeneous material base classes (template system)
142
+ "SimpleInhomogeneousModel",
143
+ "GridInhomogeneousModel",
144
+ "FullInhomogeneousModel",
145
+ # Standard materials
146
+ "VACUUM",
147
+ "AIR_STP",
148
+ "WATER",
149
+ "BK7_GLASS",
150
+ # Atmosphere materials
151
+ "ExponentialAtmosphere",
152
+ "STANDARD_ATMOSPHERE",
153
+ "create_exponential_atmosphere",
154
+ "DuctAtmosphere",
155
+ "create_duct_atmosphere",
156
+ # Atmosphere constants
157
+ "EARTH_RADIUS",
158
+ "N_SEA_LEVEL",
159
+ "SCALE_HEIGHT_DEFAULT",
160
+ # Dispersion functions
161
+ "sellmeier_refractive_index",
162
+ "cauchy_refractive_index",
163
+ # Factory functions
164
+ "create_sellmeier_material",
165
+ "create_cauchy_material",
166
+ # GPU device functions
167
+ "device_sellmeier_equation",
168
+ "device_cauchy_equation",
169
+ ]
@@ -0,0 +1,64 @@
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
+ Base Classes for Materials Module
36
+
37
+ This submodule contains the abstract base classes and template classes
38
+ for the materials system:
39
+
40
+ - MaterialField: Abstract base class for all materials
41
+ - HomogeneousMaterial: Uniform material with constant optical properties
42
+ - SimpleInhomogeneousModel: Radially-symmetric 1D materials (GPU via LUT)
43
+ - SpectralInhomogeneousModel: Radially-symmetric 2D materials with wavelength
44
+ dependence (GPU via 2D LUT)
45
+ - GridInhomogeneousModel: 3D grid-based materials (GPU via trilinear interp)
46
+ - FullInhomogeneousModel: Arbitrary Python materials (CPU-only)
47
+ """
48
+
49
+ from .material_field import MaterialField
50
+ from .homogeneous import HomogeneousMaterial
51
+ from .simple_inhomogeneous import SimpleInhomogeneousModel, EARTH_RADIUS
52
+ from .spectral_inhomogeneous import SpectralInhomogeneousModel
53
+ from .grid_inhomogeneous import GridInhomogeneousModel
54
+ from .full_inhomogeneous import FullInhomogeneousModel
55
+
56
+ __all__ = [
57
+ "MaterialField",
58
+ "HomogeneousMaterial",
59
+ "SimpleInhomogeneousModel",
60
+ "SpectralInhomogeneousModel",
61
+ "GridInhomogeneousModel",
62
+ "FullInhomogeneousModel",
63
+ "EARTH_RADIUS",
64
+ ]
@@ -0,0 +1,208 @@
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
+ Full Inhomogeneous Model (CPU-only, Arbitrary Python)
36
+
37
+ Base class for arbitrary 3D inhomogeneous materials (CPU-only).
38
+ Use this when you need maximum flexibility and cannot express your model
39
+ using the other tiers. Any Python code is allowed.
40
+ """
41
+
42
+ from abc import ABC, abstractmethod
43
+
44
+ import numpy as np
45
+ from numpy.typing import NDArray
46
+
47
+ from .material_field import MaterialField
48
+
49
+
50
+ class FullInhomogeneousModel(MaterialField, ABC):
51
+ """
52
+ Base class for arbitrary 3D inhomogeneous materials (CPU-only).
53
+
54
+ Use this when you need maximum flexibility and cannot express your model
55
+ using the other tiers. Any Python code is allowed, including external
56
+ libraries, database lookups, or complex computations.
57
+
58
+ GPU acceleration is not available for this tier. Use GradientPropagator
59
+ for CPU propagation.
60
+
61
+ User must implement:
62
+ - `get_refractive_index(x, y, z, wavelength)`
63
+
64
+ User may optionally implement:
65
+ - `get_refractive_index_gradient(x, y, z, wavelength)` (default: numerical)
66
+
67
+ Example
68
+ -------
69
+ >>> class WeatherModel(FullInhomogeneousModel):
70
+ ... def __init__(self, weather_file):
71
+ ... super().__init__(name="Weather Model")
72
+ ... self._data = load_weather_data(weather_file)
73
+ ...
74
+ ... def get_refractive_index(self, x, y, z, wavelength):
75
+ ... return self._data.interpolate(x, y, z)
76
+ ...
77
+ >>> model = WeatherModel("weather.nc")
78
+ >>> propagator = GradientPropagator() # CPU only
79
+ """
80
+
81
+ def __init__(self, name: str = "Full Inhomogeneous"):
82
+ super().__init__(name)
83
+ self._is_homogeneous = False
84
+
85
+ @abstractmethod
86
+ def get_refractive_index(
87
+ self,
88
+ x: float | NDArray[np.float64],
89
+ y: float | NDArray[np.float64],
90
+ z: float | NDArray[np.float64],
91
+ wavelength: float | NDArray[np.float64],
92
+ ) -> float | NDArray[np.float64]:
93
+ """
94
+ Get refractive index at position.
95
+
96
+ Any Python code is allowed here.
97
+
98
+ Parameters
99
+ ----------
100
+ x, y, z : float or ndarray
101
+ Position coordinates in meters
102
+ wavelength : float or ndarray
103
+ Wavelength in meters
104
+
105
+ Returns
106
+ -------
107
+ float or ndarray
108
+ Refractive index n >= 1.0
109
+ """
110
+ pass
111
+
112
+ def get_refractive_index_gradient(
113
+ self,
114
+ x: float | NDArray[np.float64],
115
+ y: float | NDArray[np.float64],
116
+ z: float | NDArray[np.float64],
117
+ wavelength: float | NDArray[np.float64],
118
+ ) -> tuple[
119
+ float | NDArray[np.float64],
120
+ float | NDArray[np.float64],
121
+ float | NDArray[np.float64],
122
+ ]:
123
+ """
124
+ Get gradient of n at position.
125
+
126
+ Default implementation uses numerical differentiation.
127
+ Override for analytical gradients.
128
+
129
+ Parameters
130
+ ----------
131
+ x, y, z : float or ndarray
132
+ Position coordinates in meters
133
+ wavelength : float or ndarray
134
+ Wavelength in meters
135
+
136
+ Returns
137
+ -------
138
+ tuple
139
+ (dn/dx, dn/dy, dn/dz) in m^-1
140
+ """
141
+ eps = 1.0 # 1 meter step
142
+
143
+ x = np.asarray(x)
144
+ y = np.asarray(y)
145
+ z = np.asarray(z)
146
+
147
+ n = self.get_refractive_index
148
+
149
+ grad_x = (n(x + eps, y, z, wavelength) - n(x - eps, y, z, wavelength)) / (
150
+ 2 * eps
151
+ )
152
+ grad_y = (n(x, y + eps, z, wavelength) - n(x, y - eps, z, wavelength)) / (
153
+ 2 * eps
154
+ )
155
+ grad_z = (n(x, y, z + eps, wavelength) - n(x, y, z - eps, wavelength)) / (
156
+ 2 * eps
157
+ )
158
+
159
+ return grad_x, grad_y, grad_z
160
+
161
+ def get_absorption_coefficient(
162
+ self,
163
+ x: float | NDArray[np.float64],
164
+ y: float | NDArray[np.float64],
165
+ z: float | NDArray[np.float64],
166
+ wavelength: float | NDArray[np.float64],
167
+ ) -> float | NDArray[np.float64]:
168
+ """Return absorption coefficient (default: 0)."""
169
+ if isinstance(x, np.ndarray):
170
+ return np.zeros_like(x)
171
+ return 0.0
172
+
173
+ def get_scattering_coefficient(
174
+ self,
175
+ x: float | NDArray[np.float64],
176
+ y: float | NDArray[np.float64],
177
+ z: float | NDArray[np.float64],
178
+ wavelength: float | NDArray[np.float64],
179
+ ) -> float | NDArray[np.float64]:
180
+ """Return scattering coefficient (default: 0)."""
181
+ if isinstance(x, np.ndarray):
182
+ return np.zeros_like(x)
183
+ return 0.0
184
+
185
+ # =========================================================================
186
+ # GPU INTERFACE - NOT SUPPORTED
187
+ # =========================================================================
188
+
189
+ @property
190
+ def gpu_material_id(self) -> int:
191
+ """GPU is not supported for FullInhomogeneousModel."""
192
+ raise NotImplementedError(
193
+ "FullInhomogeneousModel does not support GPU acceleration. "
194
+ "Use GradientPropagator for CPU propagation, or consider using "
195
+ "SimpleInhomogeneousModel or GridInhomogeneousModel for GPU support."
196
+ )
197
+
198
+ def get_gpu_kernels(self) -> dict:
199
+ """GPU is not supported for FullInhomogeneousModel."""
200
+ raise NotImplementedError(
201
+ "FullInhomogeneousModel does not support GPU acceleration."
202
+ )
203
+
204
+ def get_gpu_parameters(self) -> tuple:
205
+ """GPU is not supported for FullInhomogeneousModel."""
206
+ raise NotImplementedError(
207
+ "FullInhomogeneousModel does not support GPU acceleration."
208
+ )