DeepGPR 0.1.1__tar.gz → 0.1.3__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 (74) hide show
  1. {deepgpr-0.1.1/src/DeepGPR.egg-info → deepgpr-0.1.3}/PKG-INFO +17 -18
  2. {deepgpr-0.1.1 → deepgpr-0.1.3}/README.md +15 -16
  3. {deepgpr-0.1.1 → deepgpr-0.1.3/docs}/CHANGELOG.md +45 -10
  4. deepgpr-0.1.3/docs/Fig/2dfwiinit.png +0 -0
  5. deepgpr-0.1.3/docs/Fig/2dfwipred.png +0 -0
  6. deepgpr-0.1.3/docs/Fig/2dfwitrue.png +0 -0
  7. deepgpr-0.1.3/docs/Fig/3dfwiinit.png +0 -0
  8. deepgpr-0.1.3/docs/Fig/3dfwipred.png +0 -0
  9. deepgpr-0.1.3/docs/Fig/3dfwitrue.png +0 -0
  10. deepgpr-0.1.3/docs/Fig/example.png +0 -0
  11. {deepgpr-0.1.1 → deepgpr-0.1.3/docs}/MANIFEST.in +6 -4
  12. deepgpr-0.1.3/docs/build_support.py +20 -0
  13. {deepgpr-0.1.1 → deepgpr-0.1.3}/pyproject.toml +7 -4
  14. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/__init__.py +2 -0
  15. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/_version.py +1 -1
  16. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/inversion/regularization.py +1 -1
  17. deepgpr-0.1.3/src/DeepGPR/lib/cuda_resources.h +156 -0
  18. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr.cu +149 -93
  19. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr.dll +0 -0
  20. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr.h +5 -0
  21. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr.so +0 -0
  22. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr_cpu.c +64 -26
  23. deepgpr-0.1.3/src/DeepGPR/lib/deepgpr_cpu.dll +0 -0
  24. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr_cpu.dylib +0 -0
  25. deepgpr-0.1.3/src/DeepGPR/lib/deepgpr_cpu.so +0 -0
  26. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/native/__init__.py +2 -0
  27. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/native/abi.py +2 -0
  28. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/native/loader.py +26 -0
  29. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/model_setup.py +16 -8
  30. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/autograd.py +23 -3
  31. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/memory.py +2 -1
  32. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/modeling.py +20 -4
  33. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/pml.py +36 -13
  34. {deepgpr-0.1.1 → deepgpr-0.1.3/src/DeepGPR.egg-info}/PKG-INFO +17 -18
  35. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR.egg-info/SOURCES.txt +11 -2
  36. deepgpr-0.1.1/src/DeepGPR/lib/deepgpr_cpu.dll +0 -0
  37. deepgpr-0.1.1/src/DeepGPR/lib/deepgpr_cpu.so +0 -0
  38. {deepgpr-0.1.1 → deepgpr-0.1.3}/license +0 -0
  39. {deepgpr-0.1.1 → deepgpr-0.1.3}/requirements.txt +0 -0
  40. {deepgpr-0.1.1 → deepgpr-0.1.3}/setup.cfg +0 -0
  41. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/common.py +0 -0
  42. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/compute2.py +0 -0
  43. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/config/__init__.py +0 -0
  44. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/config/constants.py +0 -0
  45. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/config/defaults.py +0 -0
  46. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/inversion/__init__.py +0 -0
  47. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/libomp.dylib +0 -0
  48. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/multiscale.py +0 -0
  49. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/native/bridge.py +0 -0
  50. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/postprocessing/__init__.py +0 -0
  51. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/postprocessing/filters.py +0 -0
  52. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/postprocessing/io.py +0 -0
  53. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/__init__.py +0 -0
  54. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/grid.py +0 -0
  55. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/stability.py +0 -0
  56. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/wavelets.py +0 -0
  57. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/py.typed +0 -0
  58. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/__init__.py +0 -0
  59. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/fields.py +0 -0
  60. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/sampling.py +0 -0
  61. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/storage.py +0 -0
  62. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/__init__.py +0 -0
  63. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/devices.py +0 -0
  64. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/exceptions.py +0 -0
  65. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/formatting.py +0 -0
  66. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/logger.py +0 -0
  67. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/tensor_checks.py +0 -0
  68. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/validators.py +0 -0
  69. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/visualization/__init__.py +0 -0
  70. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/visualization/plotting.py +0 -0
  71. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/wavelet.py +0 -0
  72. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR.egg-info/dependency_links.txt +0 -0
  73. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR.egg-info/requires.txt +0 -0
  74. {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR.egg-info/top_level.txt +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DeepGPR
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: PyTorch and CUDA for GPR FWI
5
5
  Author-email: Lei Liu <liulei990222@gmail.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/songc0a/DeepGPR
8
8
  Project-URL: Repository, https://github.com/songc0a/DeepGPR
9
9
  Project-URL: Documentation, https://songc0a.github.io/DeepGPR/
10
- Project-URL: Changelog, https://github.com/songc0a/DeepGPR/blob/main/CHANGELOG.md
10
+ Project-URL: Changelog, https://github.com/songc0a/DeepGPR/blob/main/docs/CHANGELOG.md
11
11
  Keywords: ground penetrating radar,GPR,FDTD,full waveform inversion,PyTorch,CUDA
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Operating System :: Microsoft :: Windows
@@ -44,10 +44,10 @@ DeepGPR provides a wave propagation module for PyTorch, designed for application
44
44
 
45
45
  - 2D and 3D forward modeling of Maxwell's equations with the Finite-Difference Time-Domain (FDTD) method, for single and multiple excitations.
46
46
  - Gradients of the receiver data with respect to relative permittivity, conductivity, the initial wavefield and the source amplitudes, computed by an exact discrete adjoint.
47
- - Automatic extension of the physical model into a CPML with an independent thickness on every face. Supply only air and the target region; material gradients keep the input model shape.
47
+ - Automatic extension of the physical model into a CPML with an independent thickness on every face. Supply only air and the target region; sensitivities from replicated PML materials are summed back to the input model edges. Absorption uses a fixed `pml_max_velocity` reference (vacuum light speed by default).
48
48
  - CUDA GPU backend and a C/OpenMP CPU backend (selected automatically with `device='cpu'`).
49
49
  - Spatial FDTD order 2, 4 or 8 (`fdtd_order`), and gradient mode 2 (Ez only) or 3 (Ex, Ey, Ez).
50
- - Large models: checkpointing, DDP, temporal sub-sampling (fixed or `"auto"` from the source spectrum), E-only float32 histories (default; half the memory of E+R), histories restricted to the physical model (`wavefield_history_region="physical"`), FP16/BF16 or GPU-native INT8 wavefield histories and asynchronous offload to host memory. See [`docs/API.md`](docs/API.md) §4.3-4.6.
50
+ - Large models: checkpointing, DDP, temporal sub-sampling (fixed or `"auto"` from the source spectrum), E-only float32 histories (default; half the memory of E+R), FP16/BF16 or GPU-native INT8 wavefield histories and asynchronous offload to host memory. Material gradients with PML require `wavefield_history_region="extended"`; physical-only histories remain available for diagnostics, source/initial-state gradients and models without PML. See [`docs/API.md`](docs/API.md) §4.3-4.6.
51
51
 
52
52
  ## System requirements
53
53
 
@@ -68,8 +68,7 @@ pip install "DeepGPR[examples]" # + scipy, scikit-image, jupyter for the not
68
68
  For development from a clone:
69
69
 
70
70
  ```bash
71
- pip install -r requirements-dev.txt
72
- pip install -e .
71
+ pip install -e ".[dev,examples]"
73
72
  ```
74
73
 
75
74
  The prebuilt native libraries ship in `src/DeepGPR/lib`. To rebuild them see [`docs/BUILDING.md`](docs/BUILDING.md).
@@ -114,7 +113,7 @@ DeepGPR.visualization.plot_model(eps_r.grad, ax=ax[1], title="Gradient", cmap="s
114
113
  plt.show()
115
114
  ```
116
115
 
117
- ![result](Fig/example.png)
116
+ ![result](docs/Fig/example.png)
118
117
 
119
118
  More examples are in [`examples/`](examples) (forward modeling, 2D FWI, 3D FWI).
120
119
 
@@ -141,15 +140,15 @@ The figures show the true model, the initial model and the inverted result.
141
140
 
142
141
  | True model | Initial model | Inverted result |
143
142
  | --- | --- | --- |
144
- | ![2D true model](Fig/2dfwitrue.png) | ![2D initial model](Fig/2dfwiinit.png) | ![2D inverted result](Fig/2dfwipred.png) |
143
+ | ![2D true model](docs/Fig/2dfwitrue.png) | ![2D initial model](docs/Fig/2dfwiinit.png) | ![2D inverted result](docs/Fig/2dfwipred.png) |
145
144
 
146
145
  ### 3D FWI (central slice)
147
146
 
148
147
  | Model | Central slice |
149
148
  | --- | --- |
150
- | True model | ![3D true model central slice](Fig/3dfwitrue.png) |
151
- | Initial model | ![3D initial model central slice](Fig/3dfwiinit.png) |
152
- | Inverted result | ![3D inverted result central slice](Fig/3dfwipred.png) |
149
+ | True model | ![3D true model central slice](docs/Fig/3dfwitrue.png) |
150
+ | Initial model | ![3D initial model central slice](docs/Fig/3dfwiinit.png) |
151
+ | Inverted result | ![3D inverted result central slice](docs/Fig/3dfwipred.png) |
153
152
 
154
153
  ## API overview
155
154
 
@@ -198,10 +197,10 @@ src/DeepGPR/
198
197
  ├── utils/ logging, exceptions, validators, diagnostics
199
198
  ├── lib/ deepgpr.cu, deepgpr_cpu.c, deepgpr.h and prebuilt binaries
200
199
  ├── common.py, compute2.py, multiscale.py, wavelet.py compatibility modules
201
- docs/ API reference, build guide, code audit
200
+ docs/ API reference, build guide, changelog, manifest and Fig/
202
201
  examples/ forward, 2D FWI and 3D FWI notebooks
203
202
  tests/ unit tests, verification notebooks, benchmarks
204
- tools/ verify_equivalence.py
203
+ website/ static pages, assets, scripts/, tools/ and promo_pixel/
205
204
  ```
206
205
 
207
206
  Data flow of one `compute` call:
@@ -216,8 +215,8 @@ and the saved history.
216
215
  python -m unittest discover -s tests -p "test_*.py" # unit tests
217
216
  python -m unittest tests/test_native_abi.py # ABI check, no PyTorch needed
218
217
  python tests/run_notebook.py tests/00_local_backend_and_contracts.ipynb
219
- python tools/verify_equivalence.py --reference-src /path/to/DeepGPR-0.0.20/src/DeepGPR
220
- bash tools/run_local_validation.sh /path/to/DeepGPR-0.0.20 # rebuild CPU+CUDA libs, run everything
218
+ python website/tools/verify_equivalence.py --no-pml --reference-src /path/to/DeepGPR-0.0.20/src/DeepGPR
219
+ bash website/tools/run_local_validation.sh /path/to/DeepGPR-0.0.20 # rebuild CPU+CUDA libs, run everything
221
220
  ```
222
221
 
223
222
  Run the notebooks `00` to `09` in numeric order, followed by
@@ -232,15 +231,15 @@ bits between runs.
232
231
 
233
232
  **Reproducing results from DeepGPR ≤ 0.0.20.** 0.1.0 corrects the FIR design
234
233
  for even filter lengths, the envelope for odd trace lengths and the isotropic
235
- TV (see [`CHANGELOG.md`](CHANGELOG.md)). Use `apply_filter(..., legacy=True)`,
234
+ TV (see [`docs/CHANGELOG.md`](docs/CHANGELOG.md)). Use `apply_filter(..., legacy=True)`,
236
235
  `design_fir_filter(..., legacy=True)`, `hilbert_transform(..., legacy=True)`
237
236
  and `TVRegularization(method="legacy_isotropic")` to reproduce earlier numbers.
238
237
 
239
238
  ## Development
240
239
 
241
- - Code style: PEP 8, enforced with `ruff check src/DeepGPR tools` (configuration in `pyproject.toml`).
240
+ - Code style: PEP 8, enforced with `ruff check src/DeepGPR website/tools docs/build_support.py` (configuration in `pyproject.toml`).
242
241
  - Type hints throughout; `mypy` configuration in `pyproject.toml`.
243
- - Changes are recorded in [`CHANGELOG.md`](CHANGELOG.md); known issues and recommended native work in [`docs/AUDIT.md`](docs/AUDIT.md).
242
+ - Changes are recorded in [`docs/CHANGELOG.md`](docs/CHANGELOG.md); known issues and recommended native work in [`docs/AUDIT.md`](docs/AUDIT.md).
244
243
  - Changes to `lib/deepgpr.h` must be mirrored in `src/DeepGPR/native/abi.py`; `tests/test_native_abi.py` enforces it.
245
244
 
246
245
  ## Citation
@@ -8,10 +8,10 @@ DeepGPR provides a wave propagation module for PyTorch, designed for application
8
8
 
9
9
  - 2D and 3D forward modeling of Maxwell's equations with the Finite-Difference Time-Domain (FDTD) method, for single and multiple excitations.
10
10
  - Gradients of the receiver data with respect to relative permittivity, conductivity, the initial wavefield and the source amplitudes, computed by an exact discrete adjoint.
11
- - Automatic extension of the physical model into a CPML with an independent thickness on every face. Supply only air and the target region; material gradients keep the input model shape.
11
+ - Automatic extension of the physical model into a CPML with an independent thickness on every face. Supply only air and the target region; sensitivities from replicated PML materials are summed back to the input model edges. Absorption uses a fixed `pml_max_velocity` reference (vacuum light speed by default).
12
12
  - CUDA GPU backend and a C/OpenMP CPU backend (selected automatically with `device='cpu'`).
13
13
  - Spatial FDTD order 2, 4 or 8 (`fdtd_order`), and gradient mode 2 (Ez only) or 3 (Ex, Ey, Ez).
14
- - Large models: checkpointing, DDP, temporal sub-sampling (fixed or `"auto"` from the source spectrum), E-only float32 histories (default; half the memory of E+R), histories restricted to the physical model (`wavefield_history_region="physical"`), FP16/BF16 or GPU-native INT8 wavefield histories and asynchronous offload to host memory. See [`docs/API.md`](docs/API.md) §4.3-4.6.
14
+ - Large models: checkpointing, DDP, temporal sub-sampling (fixed or `"auto"` from the source spectrum), E-only float32 histories (default; half the memory of E+R), FP16/BF16 or GPU-native INT8 wavefield histories and asynchronous offload to host memory. Material gradients with PML require `wavefield_history_region="extended"`; physical-only histories remain available for diagnostics, source/initial-state gradients and models without PML. See [`docs/API.md`](docs/API.md) §4.3-4.6.
15
15
 
16
16
  ## System requirements
17
17
 
@@ -32,8 +32,7 @@ pip install "DeepGPR[examples]" # + scipy, scikit-image, jupyter for the not
32
32
  For development from a clone:
33
33
 
34
34
  ```bash
35
- pip install -r requirements-dev.txt
36
- pip install -e .
35
+ pip install -e ".[dev,examples]"
37
36
  ```
38
37
 
39
38
  The prebuilt native libraries ship in `src/DeepGPR/lib`. To rebuild them see [`docs/BUILDING.md`](docs/BUILDING.md).
@@ -78,7 +77,7 @@ DeepGPR.visualization.plot_model(eps_r.grad, ax=ax[1], title="Gradient", cmap="s
78
77
  plt.show()
79
78
  ```
80
79
 
81
- ![result](Fig/example.png)
80
+ ![result](docs/Fig/example.png)
82
81
 
83
82
  More examples are in [`examples/`](examples) (forward modeling, 2D FWI, 3D FWI).
84
83
 
@@ -105,15 +104,15 @@ The figures show the true model, the initial model and the inverted result.
105
104
 
106
105
  | True model | Initial model | Inverted result |
107
106
  | --- | --- | --- |
108
- | ![2D true model](Fig/2dfwitrue.png) | ![2D initial model](Fig/2dfwiinit.png) | ![2D inverted result](Fig/2dfwipred.png) |
107
+ | ![2D true model](docs/Fig/2dfwitrue.png) | ![2D initial model](docs/Fig/2dfwiinit.png) | ![2D inverted result](docs/Fig/2dfwipred.png) |
109
108
 
110
109
  ### 3D FWI (central slice)
111
110
 
112
111
  | Model | Central slice |
113
112
  | --- | --- |
114
- | True model | ![3D true model central slice](Fig/3dfwitrue.png) |
115
- | Initial model | ![3D initial model central slice](Fig/3dfwiinit.png) |
116
- | Inverted result | ![3D inverted result central slice](Fig/3dfwipred.png) |
113
+ | True model | ![3D true model central slice](docs/Fig/3dfwitrue.png) |
114
+ | Initial model | ![3D initial model central slice](docs/Fig/3dfwiinit.png) |
115
+ | Inverted result | ![3D inverted result central slice](docs/Fig/3dfwipred.png) |
117
116
 
118
117
  ## API overview
119
118
 
@@ -162,10 +161,10 @@ src/DeepGPR/
162
161
  ├── utils/ logging, exceptions, validators, diagnostics
163
162
  ├── lib/ deepgpr.cu, deepgpr_cpu.c, deepgpr.h and prebuilt binaries
164
163
  ├── common.py, compute2.py, multiscale.py, wavelet.py compatibility modules
165
- docs/ API reference, build guide, code audit
164
+ docs/ API reference, build guide, changelog, manifest and Fig/
166
165
  examples/ forward, 2D FWI and 3D FWI notebooks
167
166
  tests/ unit tests, verification notebooks, benchmarks
168
- tools/ verify_equivalence.py
167
+ website/ static pages, assets, scripts/, tools/ and promo_pixel/
169
168
  ```
170
169
 
171
170
  Data flow of one `compute` call:
@@ -180,8 +179,8 @@ and the saved history.
180
179
  python -m unittest discover -s tests -p "test_*.py" # unit tests
181
180
  python -m unittest tests/test_native_abi.py # ABI check, no PyTorch needed
182
181
  python tests/run_notebook.py tests/00_local_backend_and_contracts.ipynb
183
- python tools/verify_equivalence.py --reference-src /path/to/DeepGPR-0.0.20/src/DeepGPR
184
- bash tools/run_local_validation.sh /path/to/DeepGPR-0.0.20 # rebuild CPU+CUDA libs, run everything
182
+ python website/tools/verify_equivalence.py --no-pml --reference-src /path/to/DeepGPR-0.0.20/src/DeepGPR
183
+ bash website/tools/run_local_validation.sh /path/to/DeepGPR-0.0.20 # rebuild CPU+CUDA libs, run everything
185
184
  ```
186
185
 
187
186
  Run the notebooks `00` to `09` in numeric order, followed by
@@ -196,15 +195,15 @@ bits between runs.
196
195
 
197
196
  **Reproducing results from DeepGPR ≤ 0.0.20.** 0.1.0 corrects the FIR design
198
197
  for even filter lengths, the envelope for odd trace lengths and the isotropic
199
- TV (see [`CHANGELOG.md`](CHANGELOG.md)). Use `apply_filter(..., legacy=True)`,
198
+ TV (see [`docs/CHANGELOG.md`](docs/CHANGELOG.md)). Use `apply_filter(..., legacy=True)`,
200
199
  `design_fir_filter(..., legacy=True)`, `hilbert_transform(..., legacy=True)`
201
200
  and `TVRegularization(method="legacy_isotropic")` to reproduce earlier numbers.
202
201
 
203
202
  ## Development
204
203
 
205
- - Code style: PEP 8, enforced with `ruff check src/DeepGPR tools` (configuration in `pyproject.toml`).
204
+ - Code style: PEP 8, enforced with `ruff check src/DeepGPR website/tools docs/build_support.py` (configuration in `pyproject.toml`).
206
205
  - Type hints throughout; `mypy` configuration in `pyproject.toml`.
207
- - Changes are recorded in [`CHANGELOG.md`](CHANGELOG.md); known issues and recommended native work in [`docs/AUDIT.md`](docs/AUDIT.md).
206
+ - Changes are recorded in [`docs/CHANGELOG.md`](docs/CHANGELOG.md); known issues and recommended native work in [`docs/AUDIT.md`](docs/AUDIT.md).
208
207
  - Changes to `lib/deepgpr.h` must be mirrored in `src/DeepGPR/native/abi.py`; `tests/test_native_abi.py` enforces it.
209
208
 
210
209
  ## Citation
@@ -6,8 +6,21 @@ All notable changes to this project are documented here. The format follows
6
6
 
7
7
  ## [Unreleased] — History memory and CUDA adjoint performance
8
8
 
9
+ ### Repository layout
10
+
11
+ - Website tools, statistics scripts and pixel film sources now live under
12
+ `website/tools`, `website/scripts` and `website/promo_pixel`. Their input/output
13
+ paths and CI commands follow the new locations; Pages publishes public assets
14
+ without the source tool directories.
15
+ - Figures, changelog and the source-distribution template now live in `docs`.
16
+ The setuptools build hook reads `docs/MANIFEST.in`, including when building a
17
+ wheel from a source archive. Documentation and package metadata links updated.
18
+ - Development dependencies are installed with `pip install -e ".[dev,examples]"`.
19
+ Removed the duplicate development requirements file and local assistant
20
+ configuration, and cleaned embedded tool attribution from media metadata.
21
+
9
22
  Measurements, protocol and per-item decisions:
10
- [`tests/profiling_results/history_adjoint_gpu_report.md`](tests/profiling_results/history_adjoint_gpu_report.md).
23
+ [`tests/profiling_results/history_adjoint_gpu_report.md`](../tests/profiling_results/history_adjoint_gpu_report.md).
11
24
 
12
25
  ### Added
13
26
 
@@ -29,14 +42,21 @@ Measurements, protocol and per-item decisions:
29
42
  capability probe `deepgpr_supports_rhs_reconstruction` (ABI 6 unchanged);
30
43
  older libraries fall back to E+R.
31
44
  - `wavefield_history_region` (`"extended"` default, `"physical"`). `"physical"`
32
- stores E/R histories only on the physical model cells (CPML cells never get
33
- a material gradient), so history memory falls with the cell count and
34
- gradients are unchanged. INT8 histories widen the box to whole tiles of the
45
+ stores E/R histories only on physical cells for forward diagnostics,
46
+ source/initial-state gradients, or models without PML. Material inversion
47
+ with PML requires `"extended"`. INT8 histories widen the box to whole tiles of the
35
48
  full-grid tiling so tiles and scales are identical to `"extended"`. New probe
36
49
  `deepgpr_supports_physical_history`; saved files record the region.
37
50
 
38
51
  ### Performance
39
52
 
53
+ - CUDA async-offload calls reuse streams, synchronization events and staging
54
+ buffers (audit N-8). Workspaces are exclusive to each call, partitioned by
55
+ device, and cached only after successful synchronization. At most one idle
56
+ workspace with up to 64 MiB of staging is retained per device;
57
+ `DeepGPR.clear_cuda_resource_cache(device=None)` releases idle resources.
58
+ Native forward/backward signatures and ABI 6 are unchanged. Measurements:
59
+ [CUDA resource cache report](../tests/profiling_results/cuda_resource_cache_report.md).
40
60
  - CUDA full-grid kernels (E/H update and adjoint) take the shot from
41
61
  `blockIdx.y` and decode `(i, j, k)` from a 32-bit per-shot index with a
42
62
  multiply-high divider instead of four 64-bit `/` and `%` per thread. Grids
@@ -75,6 +95,21 @@ Measurements, protocol and per-item decisions:
75
95
 
76
96
  ### Changed
77
97
 
98
+ - PML materials remain derived from the physical model, with CPU/CUDA material
99
+ sensitivities retained throughout PML and summed back to model edges,
100
+ intersections and corners. Absorbing profiles use `pml_max_velocity`, a fixed
101
+ reference speed (default vacuum), instead of changing boundary material
102
+ averages. Keep it fixed during optimization, FD checks and checkpointing.
103
+ Old native libraries are rejected for PML material gradients via the new
104
+ `deepgpr_supports_pml_material_gradients` probe; ABI 6 is unchanged.
105
+ - Exactly zero local material sensitivities remain zero even when an
106
+ unobservable outer-CPML state cotangent overflows in long lossless runs.
107
+ CPU, CUDA and INT8 avoid `0 * Inf` without clipping nonzero sensitivities
108
+ or changing the forward equations. Arbitrary long-time initial-state
109
+ cotangents can still overflow on these outer cells.
110
+ - Corrected material gradients at Yee components that do not execute the base
111
+ electric update; source and CPML corrections still contribute through `cb`.
112
+ - Total variation losses preserve the input dtype, including float64.
78
113
  - An explicit `model_gradient_sampling_interval > 1` no longer always raises a
79
114
  `RuntimeWarning`; it warns (and states the bound) only above
80
115
  `floor(1 / (4 f_max dt))`. Intervals inside the bound are logged at INFO.
@@ -93,7 +128,7 @@ Measurements, protocol and per-item decisions:
93
128
 
94
129
  This release reorganises the Python package into a layered, typed and
95
130
  documented code base and fixes the defects found in the review
96
- ([`docs/AUDIT.md`](docs/AUDIT.md)).
131
+ ([`docs/AUDIT.md`](AUDIT.md)).
97
132
 
98
133
  **What changes numerically** (all deliberate, see [Numerical fixes](#numerical-fixes)):
99
134
 
@@ -202,7 +237,7 @@ from the 0.1.0 sources. The CUDA (`deepgpr.so`, `deepgpr.dll`) and the Windows /
202
237
  macOS CPU binaries are still the 0.0.20 builds until the *Build Native
203
238
  Libraries* workflow runs; they load and compute as before but without error
204
239
  reporting (and, for the CPU ones, without the deterministic adjoint).
205
- `tools/run_local_validation.sh` rebuilds the CPU and CUDA libraries locally
240
+ `website/tools/run_local_validation.sh` rebuilds the CPU and CUDA libraries locally
206
241
  and runs the full validation.
207
242
 
208
243
  ### Fixed
@@ -234,7 +269,7 @@ and runs the full validation.
234
269
  (same `forward_wavefield_HH-MM[_NN].pt` scheme). Partially written files are
235
270
  removed on failure.
236
271
  - **Invalid requirement shipped in the wheel.** `src/DeepGPR/requirements.txt`
237
- contained `torch+cu` and was packaged via `MANIFEST.in`; removed.
272
+ contained `torch+cu` and was packaged via `docs/MANIFEST.in`; removed.
238
273
  - Error message of `apply_filter` used full-width punctuation (`。`).
239
274
 
240
275
  ### Changed
@@ -300,7 +335,7 @@ measurable:
300
335
  - `tests/test_signal_and_regularization.py` (FIR, envelope and TV against
301
336
  independent NumPy implementations; legacy switches).
302
337
  - `tests/test_cpu_determinism.py` (bitwise equality for 1, 2 and 5 threads).
303
- - `tools/verify_equivalence.py` (comparison with a reference release: forward
338
+ - `website/tools/verify_equivalence.py` (comparison with a reference release: forward
304
339
  and gradient tolerances, legacy reproduction, determinism, error reporting).
305
340
  - `legacy=` keyword for `design_fir_filter`, `apply_filter`,
306
341
  `hilbert_transform`; `remove_dc=` for `hilbert_transform`; `epsilon=` and
@@ -308,7 +343,7 @@ measurable:
308
343
  - Native functions `deepgpr_supports_error_reporting`, `deepgpr_last_error`,
309
344
  `deepgpr_clear_last_error`, `deepgpr_deterministic_adjoint` (ABI 6, additive).
310
345
  - `.github/workflows/quality.yml` (ruff, ABI test, CPU unit tests, equivalence).
311
- - `requirements.txt`, `requirements-dev.txt`, ruff/mypy/pytest configuration.
346
+ - `requirements.txt`, development extras in `pyproject.toml`, ruff/mypy/pytest configuration.
312
347
 
313
348
  ### Removed / internal changes
314
349
 
@@ -353,7 +388,7 @@ which is byte-identical to the 0.0.21 PyPI release):
353
388
 
354
389
  | Check | Scope | Result |
355
390
  |---|---|---|
356
- | `tools/verify_equivalence.py` | CPU and CUDA: 2D/3D × order 2/4/8 × fp32/fp16/bf16 × sampling 1/3, no/asymmetric PML, forward-only, mode 3, checkpoint segments; CUDA INT8 (2D/3D), async offload, fp16 conversion backends; legacy switches; error reporting; CPU determinism for 1/2/4/8 threads | all passed; forward outputs **bitwise identical**, gradients within 1.9·10⁻⁶ (CPU) / 4.7·10⁻⁷ (CUDA) relative |
391
+ | `website/tools/verify_equivalence.py` | CPU and CUDA: 2D/3D × order 2/4/8 × fp32/fp16/bf16 × sampling 1/3, no/asymmetric PML, forward-only, mode 3, checkpoint segments; CUDA INT8 (2D/3D), async offload, fp16 conversion backends; legacy switches; error reporting; CPU determinism for 1/2/4/8 threads | all passed; forward outputs **bitwise identical**, gradients within 1.9·10⁻⁶ (CPU) / 4.7·10⁻⁷ (CUDA) relative |
357
392
  | Unit tests | 105 tests, `OMP_NUM_THREADS` = 1, 2, 4, 8 | all passed (1 skip: needs two GPUs) |
358
393
  | Verification notebooks `tests/00`–`09`, `99` | `DEEPGPR_REQUIRE_CUDA=1` | 108 checks passed, CUDA parity evidence present |
359
394
  | CI simulation | Python 3.12, PyTorch 2.x CPU: unit tests and `verify_equivalence.py --device cpu --quick`; `ruff check src/DeepGPR tools` | all passed |
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,5 +1,4 @@
1
1
  include README.md
2
- include CHANGELOG.md
3
2
  include license
4
3
  include pyproject.toml
5
4
  include requirements.txt
@@ -9,14 +8,17 @@ recursive-include src/DeepGPR *.py *.typed *.cu *.h *.c *.dll *.so *.dylib
9
8
  # Exclude local state and repository-only resources.
10
9
  prune .*
11
10
  prune validation
12
- prune Fig
13
11
  prune docs
14
12
  prune examples
15
- prune scripts
16
13
  prune tests
17
- prune tools
18
14
  prune website
19
15
 
16
+ # Keep the relocated manifest and its build hook available in the sdist.
17
+ include docs/MANIFEST.in
18
+ include docs/build_support.py
19
+ include docs/CHANGELOG.md
20
+ recursive-include docs/Fig *.png
21
+
20
22
  global-exclude .DS_Store
21
23
  global-exclude *.py[cod]
22
24
  global-exclude __pycache__
@@ -0,0 +1,20 @@
1
+ """Keep the source-distribution manifest alongside the project documentation."""
2
+
3
+ from pathlib import Path
4
+
5
+ from setuptools.command.egg_info import egg_info, manifest_maker
6
+
7
+
8
+ class EggInfo(egg_info):
9
+ """Use docs/MANIFEST.in when setuptools generates the source file list."""
10
+
11
+ def find_sources(self):
12
+ template = Path("docs/MANIFEST.in")
13
+ if not template.is_file():
14
+ raise FileNotFoundError("Source distribution template missing: docs/MANIFEST.in")
15
+ maker = manifest_maker(self.distribution)
16
+ maker.ignore_egg_info_dir = self.ignore_egg_info_in_manifest
17
+ maker.template = str(template)
18
+ maker.manifest = str(Path(self.egg_info) / "SOURCES.txt")
19
+ maker.run()
20
+ self.filelist = maker.filelist
@@ -39,12 +39,15 @@ dev = ["ruff>=0.5", "mypy>=1.8", "pytest>=7", "nbformat", "nbclient"]
39
39
  Homepage = "https://github.com/songc0a/DeepGPR"
40
40
  Repository = "https://github.com/songc0a/DeepGPR"
41
41
  Documentation = "https://songc0a.github.io/DeepGPR/"
42
- Changelog = "https://github.com/songc0a/DeepGPR/blob/main/CHANGELOG.md"
42
+ Changelog = "https://github.com/songc0a/DeepGPR/blob/main/docs/CHANGELOG.md"
43
43
 
44
44
  [tool.setuptools]
45
- package-dir = { "" = "src" }
45
+ package-dir = { "" = "src", docs = "docs" }
46
46
  include-package-data = true
47
47
 
48
+ [tool.setuptools.cmdclass]
49
+ egg_info = "docs.build_support.EggInfo"
50
+
48
51
  [tool.setuptools.dynamic]
49
52
  version = { attr = "DeepGPR._version.__version__" }
50
53
 
@@ -77,8 +80,8 @@ DeepGPR = [
77
80
  [tool.ruff]
78
81
  line-length = 100
79
82
  target-version = "py38"
80
- src = ["src", "tests", "tools"]
81
- extend-exclude = ["tests/*.ipynb", "examples", "website", "scripts"]
83
+ src = ["src", "tests", "website/tools"]
84
+ extend-exclude = ["tests/*.ipynb", "examples", "website/assets", "website/scripts", "website/promo_pixel"]
82
85
 
83
86
  [tool.ruff.lint]
84
87
  select = ["E", "F", "W", "B", "UP", "SIM", "C4"]
@@ -34,6 +34,7 @@ from __future__ import annotations
34
34
  from . import config, utils
35
35
  from ._version import __version__
36
36
  from .native.loader import (
37
+ clear_cuda_resource_cache,
37
38
  get_deepgpr_lib,
38
39
  get_deepgpr_library_path,
39
40
  set_library_fdtd_order,
@@ -97,6 +98,7 @@ __all__ = [
97
98
  "check_cfl",
98
99
  "check_tensors_for_nan_inf",
99
100
  "checkpoint_initial_field",
101
+ "clear_cuda_resource_cache",
100
102
  "common",
101
103
  "compute",
102
104
  "compute2",
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for the package version."""
2
2
 
3
- __version__ = "0.1.1"
3
+ __version__ = "0.1.3"
@@ -137,7 +137,7 @@ class TVRegularization(nn.Module):
137
137
  raise ValueError("TVRegularization needs at least one of ep or sigma.")
138
138
  reference = ep if ep is not None else sigma
139
139
  assert reference is not None
140
- loss = torch.tensor(0.0, device=reference.device)
140
+ loss = reference.new_zeros(())
141
141
  if ep is not None and self.weight_ep > 0:
142
142
  loss += self.weight_ep * self._compute_tv(ep)
143
143
  if sigma is not None and self.weight_sigma > 0:
@@ -0,0 +1,156 @@
1
+ #ifndef DEEPGPR_CUDA_RESOURCES_H
2
+ #define DEEPGPR_CUDA_RESOURCES_H
3
+
4
+ #include <cuda_runtime.h>
5
+ #include <list>
6
+ #include <mutex>
7
+ #include <new>
8
+ #include <utility>
9
+
10
+ /* A workspace is leased exclusively to one native call. Only drained,
11
+ * successful calls return it to the cache; histories remain caller-owned. */
12
+ struct CudaAsyncWorkspace {
13
+ int device = -1;
14
+ unsigned char* e = nullptr;
15
+ unsigned char* r = nullptr;
16
+ size_t e_capacity = 0;
17
+ size_t r_capacity = 0;
18
+ cudaStream_t streams[2] = {nullptr, nullptr};
19
+ cudaEvent_t events[4] = {nullptr, nullptr, nullptr, nullptr};
20
+
21
+ CudaAsyncWorkspace() = default;
22
+ CudaAsyncWorkspace(const CudaAsyncWorkspace&) = delete;
23
+ CudaAsyncWorkspace& operator=(const CudaAsyncWorkspace&) = delete;
24
+
25
+ void swap(CudaAsyncWorkspace& other) noexcept
26
+ {
27
+ std::swap(device, other.device);
28
+ std::swap(e, other.e);
29
+ std::swap(r, other.r);
30
+ std::swap(e_capacity, other.e_capacity);
31
+ std::swap(r_capacity, other.r_capacity);
32
+ for (int i = 0; i < 2; ++i) std::swap(streams[i], other.streams[i]);
33
+ for (int i = 0; i < 4; ++i) std::swap(events[i], other.events[i]);
34
+ }
35
+
36
+ ~CudaAsyncWorkspace()
37
+ {
38
+ if (device < 0) return;
39
+ int previous;
40
+ // During runtime shutdown CUDA may already be unavailable.
41
+ if (cudaGetDevice(&previous) != cudaSuccess) return;
42
+ if (previous != device && cudaSetDevice(device) != cudaSuccess) return;
43
+ for (auto stream : streams) {
44
+ if (stream) cudaStreamSynchronize(stream);
45
+ }
46
+ if (e) cudaFree(e);
47
+ if (r) cudaFree(r);
48
+ for (auto event : events) {
49
+ if (event) cudaEventDestroy(event);
50
+ }
51
+ for (auto stream : streams) {
52
+ if (stream) cudaStreamDestroy(stream);
53
+ }
54
+ if (previous != device) cudaSetDevice(previous);
55
+ }
56
+
57
+ static cudaError_t reserve(unsigned char*& pointer, size_t& capacity, size_t bytes)
58
+ {
59
+ if (bytes <= capacity) return cudaSuccess;
60
+ // The old workspace is idle. Release before growing to avoid holding
61
+ // both old and new allocations at peak memory usage.
62
+ if (pointer) {
63
+ cudaError_t error = cudaFree(pointer);
64
+ if (error != cudaSuccess) return error;
65
+ pointer = nullptr;
66
+ capacity = 0;
67
+ }
68
+ cudaError_t error = cudaMalloc(&pointer, bytes);
69
+ if (error == cudaSuccess) capacity = bytes;
70
+ return error;
71
+ }
72
+
73
+ cudaError_t prepare(size_t e_bytes, size_t r_bytes)
74
+ {
75
+ for (auto& stream : streams) {
76
+ if (!stream) {
77
+ cudaError_t error = cudaStreamCreate(&stream);
78
+ if (error != cudaSuccess) return error;
79
+ }
80
+ }
81
+ for (auto& event : events) {
82
+ if (!event) {
83
+ cudaError_t error = cudaEventCreateWithFlags(&event, cudaEventDisableTiming);
84
+ if (error != cudaSuccess) return error;
85
+ }
86
+ }
87
+ cudaError_t error = reserve(e, e_capacity, e_bytes);
88
+ if (error != cudaSuccess) return error;
89
+ return reserve(r, r_capacity, r_bytes);
90
+ }
91
+ };
92
+
93
+ class CudaAsyncCache {
94
+ std::mutex mutex_;
95
+ std::list<CudaAsyncWorkspace> idle_;
96
+
97
+ public:
98
+ // Retain at most one idle workspace and 64 MiB of staging per device.
99
+ // Oversized calls still run, but their workspace is released on return.
100
+ static constexpr size_t max_bytes = 64 * size_t(1024) * 1024;
101
+
102
+ void take(int device, CudaAsyncWorkspace& workspace)
103
+ {
104
+ std::lock_guard<std::mutex> lock(mutex_);
105
+ for (auto it = idle_.begin(); it != idle_.end(); ++it) {
106
+ if (it->device == device) {
107
+ workspace.swap(*it);
108
+ idle_.erase(it);
109
+ return;
110
+ }
111
+ }
112
+ workspace.device = device;
113
+ }
114
+
115
+ void put(CudaAsyncWorkspace& workspace)
116
+ {
117
+ if (workspace.e_capacity > max_bytes
118
+ || workspace.r_capacity > max_bytes - workspace.e_capacity) return;
119
+ std::lock_guard<std::mutex> lock(mutex_);
120
+ for (const auto& entry : idle_) {
121
+ if (entry.device == workspace.device) return;
122
+ }
123
+ // A cache miss must not turn a successful solver call into an error.
124
+ try {
125
+ idle_.emplace_back();
126
+ } catch (const std::bad_alloc&) {
127
+ return;
128
+ }
129
+ idle_.back().swap(workspace);
130
+ }
131
+
132
+ void clear(int device)
133
+ {
134
+ CudaAsyncWorkspace discarded;
135
+ {
136
+ std::lock_guard<std::mutex> lock(mutex_);
137
+ for (auto it = idle_.begin(); it != idle_.end(); ++it) {
138
+ if (it->device == device) {
139
+ discarded.swap(*it);
140
+ idle_.erase(it);
141
+ break;
142
+ }
143
+ }
144
+ }
145
+ // CUDA calls happen outside the lock. Active calls own separate
146
+ // workspaces and may repopulate the cache after clear() returns.
147
+ }
148
+ };
149
+
150
+ inline CudaAsyncCache& cuda_async_cache()
151
+ {
152
+ static CudaAsyncCache cache;
153
+ return cache;
154
+ }
155
+
156
+ #endif