Skip to content

Commit 566c912

Browse files
authored
Merge pull request #677 from waltsims/update-0.6.x-strategy
Add 0.6.x subplans: C-order migration, example porting, axisymmetric …
2 parents 10296a3 + 28d915a commit 566c912

1 file changed

Lines changed: 146 additions & 20 deletions

File tree

plans/release-strategy.md

Lines changed: 146 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ This release strategy brings the unified solver architecture to fruition.
99
| Version | Milestone | Focus |
1010
|---------|-----------|-------|
1111
| **0.5.0** | Finalize master/main | Stabilize current codebase |
12-
| **0.6.0** | Python Solver + Unified API + Deprecation | Python solver, `kspaceFirstOrder()` kwargs, deprecation warnings |
12+
| **0.6.0** | Python Solver + Unified API + Deprecation | Python solver, `kspaceFirstOrder()` kwargs, Future warnings |
13+
| **0.6.1** | C-order Migration (Helpers) | Migrate utils/helpers from F-order to C-order, keep legacy API working |
14+
| **0.6.2** | Example Migration | Port remaining examples to new `kspaceFirstOrder()` API |
15+
| **0.6.3** | Axisymmetric Support | Axisymmetric solver in new API, port AS examples |
1316
| **0.7.0** | CLI (`kwp`) | Command-line interface for running simulations |
1417
| **1.0.0** | Clean Release | Remove deprecated code. Simple, readable, fast. |
1518
| **2.0.0** | Performance & Scale | nanobind CUDA, MPI, Devito, multi-GPU |
@@ -27,7 +30,7 @@ This release strategy brings the unified solver architecture to fruition.
2730

2831
---
2932

30-
## Phase 2: v0.6.0 - Native Solver + Unified API + Deprecation
33+
## Phase 2: v0.6.0 - Native Solver + Unified API + Future
3134

3235
**Goal:** Ship a pure Python/CuPy native solver, create a single entry point with kwargs, and deprecate the old API. Three things in one release.
3336

@@ -97,14 +100,14 @@ def kspaceFirstOrder2D(kgrid, source, sensor, medium,
97100

98101
**Create:** `kwave/solvers/serializer.py` - Simple HDF5 writer (~200 lines)
99102

100-
### 2c: Deprecation Warnings
103+
### 2c: Future Warnings
101104

102-
**Add deprecation warnings on old API:**
105+
**Add Future warnings on old API:**
103106
```python
104107
warnings.warn(
105108
"SimulationOptions is deprecated. Use kspaceFirstOrder() kwargs instead. "
106109
"See https://waltersimson.com/k-wave-python/migration",
107-
DeprecationWarning
110+
FutureWarning
108111
)
109112
```
110113

@@ -117,7 +120,101 @@ warnings.warn(
117120
- `tests/test_native_solver.py` - parity with C++ backend
118121
- `tests/test_cupy_backend.py` - GPU acceleration (when CUDA available)
119122
- `tests/test_unified_api.py` - new kwargs API
120-
- `tests/test_deprecation_warnings.py` - verify warnings emitted
123+
- `tests/test_Future_warnings.py` - verify warnings emitted
124+
125+
---
126+
127+
## Phase 2.1: v0.6.1 - C-order Migration (Helpers)
128+
129+
**Goal:** Migrate helper/utility code from Fortran-order to C-order internally, while keeping the legacy API functional. No structural API changes — Future warnings only. Fix hacky shaping/indexing throughout.
130+
131+
**Scope:** 55 occurrences of `order="F"` across 10 files. Migrate where possible, keep F-order only at explicit boundaries.
132+
133+
**Migrate (internal helpers — safe to convert):**
134+
135+
| File | `order="F"` count | Notes |
136+
|------|-------------------|-------|
137+
| `kwave/utils/matlab.py` | 11 | reshape, flatten, unflatten utilities |
138+
| `kwave/kgrid.py` | 8 | Grid coordinate generation |
139+
| `kwave/utils/mapgen.py` | 6 | Map generation |
140+
| `kwave/utils/conversion.py` | 2 | Unit conversion |
141+
| `kwave/utils/matrix.py` | 1 | Matrix utilities |
142+
| `kwave/solvers/kspace_solver.py` | 19 | Audit each: keep F-order only at `simulate_from_dicts` boundary. Convert internal field storage, `_expand_to_grid`, `_build_source_op`, sensor mask extraction. |
143+
| `kwave/kspaceFirstOrder.py` | 1 | Likely removable |
144+
145+
**Keep as-is (fixed boundaries):**
146+
147+
| File | `order="F"` count | Reason |
148+
|------|-------------------|--------|
149+
| `kwave/solvers/cpp_simulation.py` | 3 | C++ binary expects F-order HDF5 |
150+
| `kwave/kWaveSimulation.py` | 1 | Legacy, deleted in v1.0.0 |
151+
| `kwave/kWaveSimulation_helper/*` | 3 | Legacy, deleted in v1.0.0 |
152+
153+
**Testing:**
154+
- All existing tests must pass (no behavioral change)
155+
- Add `tests/test_memory_layout.py`: verify C/F-order input produces identical results, `simulate_from_dicts` round-trips correctly, `cpp_simulation` writes correct F-order HDF5
156+
157+
---
158+
159+
## Phase 2.2: v0.6.2 - Example Migration
160+
161+
**Goal:** Port remaining examples from legacy `kspaceFirstOrder2D/3D` to `kspaceFirstOrder()`, validated against MATLAB reference outputs.
162+
163+
### Strategy
164+
165+
Port examples one at a time using MATLAB as ground truth — not old Python results. Use the k-wave-cupy interop layer as the bridge between MATLAB and Python.
166+
167+
**Per-example workflow:**
168+
169+
1. **MATLAB reference** — Run the example in MATLAB k-Wave, save outputs to `.mat`
170+
2. **k-wave-cupy validation** — Call the Python solver from MATLAB via k-wave-cupy (`simulate_from_dicts`). Compare against MATLAB output. This catches F/C ordering and interop issues at the boundary.
171+
3. **Standalone Python port** — Port the example to `kspaceFirstOrder()`, compare against the same MATLAB `.mat` reference
172+
4. **CI fixture** — Add the MATLAB `.mat` as a reference test in `tests/integration/`
173+
174+
**Why k-wave-cupy first:** The interop layer handles F→C conversion at the boundary. Validating there first means ordering bugs are caught before they propagate to the standalone Python example. Once the k-wave-cupy version matches MATLAB, the Python port is a straightforward translation.
175+
176+
**Order of work:**
177+
1. Migrate example in k-wave-cupy repo (MATLAB calls Python solver)
178+
2. Validate against MATLAB reference output
179+
3. Port the standalone Python example in k-wave-python
180+
4. Add integration test with `.mat` fixture
181+
182+
### Examples to port
183+
184+
| Example | Blocker | Resolution |
185+
|---------|---------|------------|
186+
| `pr_2D_TR_line_sensor`, `pr_3D_TR_planar_sensor` | `TimeReversal` class uses legacy API internally | Refactor `TimeReversal` to call `kspaceFirstOrder()` |
187+
| `us_defining_transducer`, `us_beam_patterns`, `us_bmode_linear_transducer`, `us_bmode_phased_array` | `NotATransducer`-as-source pipeline untested with new API | Validate transducer pipeline end-to-end via k-wave-cupy first |
188+
| `checkpointing/checkpoint.py` | `checkpoint_file`/`checkpoint_timesteps` not exposed in new API | Add checkpoint kwargs to `kspaceFirstOrder()` |
189+
190+
---
191+
192+
## Phase 2.3: v0.6.3 - Axisymmetric Support
193+
194+
**Goal:** Add axisymmetric simulation to `kspaceFirstOrder()` and port AS examples.
195+
196+
**What axisymmetric means:** Dimensionality reduction for problems with cylindrical symmetry. A 3D symmetric problem is simulated on a 2D (r, z) half-domain; a 2D symmetric problem on a 1D half-domain. Results are mirrored around the symmetry axis to reconstruct the full field.
197+
198+
**Current state:** `kspaceFirstOrderAS.py` / `kspaceFirstOrderASC.py` are standalone entry points using the legacy `kWaveSimulation` pipeline. The new API hardcodes `axisymmetric_flag=0`.
199+
200+
**Design:** Not a separate solver — a wrapper around `kspaceFirstOrder()` that:
201+
1. Takes `axisymmetric=True` kwarg
202+
2. Reduces the grid to a half-domain (y ≥ 0 = radial direction)
203+
3. Adds radial symmetry terms: special PML at axis (no absorption at y=0), expanded grid for FFT symmetries (WSWA: 4× radial, WSWS: 2×-2), radial coordinate vectors for geometric source terms
204+
4. Runs the lower-dimensional simulation via `Simulation`
205+
5. Mirrors results around the axis for output
206+
207+
**Legacy mapping:** `kspaceFirstOrderAS``kspaceFirstOrder(..., axisymmetric=True, backend="python")`, `kspaceFirstOrderASC``kspaceFirstOrder(..., axisymmetric=True, backend="cpp")`
208+
209+
**Constraints:** Staggered grid mandatory (`use_sg=True` enforced). Viscous absorption only (`alpha_power=2` fixed).
210+
211+
**Tasks:**
212+
1. Add `axisymmetric: bool = False` kwarg to `kspaceFirstOrder()`
213+
2. Implement radial symmetry pre/post-processing in `kspaceFirstOrder()` (grid reduction, PML axis handling, result mirroring)
214+
3. Add radial terms to `Simulation` class (geometric source terms for (r, z) grid)
215+
4. Port `at_circular_piston_AS`, `at_focused_bowl_AS` using the v0.6.2 MATLAB-first workflow
216+
5. Validate against MATLAB references
217+
6. Deprecate `kspaceFirstOrderAS` / `kspaceFirstOrderASC`
121218

122219
---
123220

@@ -141,6 +238,17 @@ warnings.warn(
141238

142239
**Impact:** ~5700 lines → ~1200 lines (-79%)
143240

241+
### Memory Layout and Indexing (v1.0.0)
242+
243+
By v1.0.0, the F→C migration from v0.6.1 should be complete. What remains:
244+
245+
- **C++ HDF5 serialization** (`cpp_simulation.py`) — F-order + 1-based. Stays forever (binary expects this).
246+
- **MATLAB interop** (`simulate_from_dicts`) — converts F→C on input, C→F on output. Single conversion boundary.
247+
- **kWaveArray** — rewrite `combine_sensor_data` and `get_distributed_source_signal` to use `np.where` (0-based) and C-order.
248+
- **sensor.record_start_index** — require 0-based (deprecated 1-based in v0.6.1).
249+
250+
**Principle:** Python-native (C-order, 0-based) everywhere internally. MATLAB compatibility at two explicit boundaries: (1) `simulate_from_dicts` for k-wave-cupy interop, (2) `cpp_simulation._write_hdf5` for the C++ binary.
251+
144252
---
145253

146254
## Phase 3.5: v0.7.0 - CLI (`kwp`)
@@ -207,15 +315,30 @@ result = kspaceFirstOrder(kgrid, medium, source, sensor,
207315
## Testing Strategy
208316

209317
**Existing (keep):**
210-
- MATLAB reference tests via CI
211-
- Multi-platform pytest (Windows, Ubuntu, macOS)
212-
- Python 3.10-3.13 coverage
318+
- MATLAB reference tests via CI (66 MATLAB collectors → `.mat` fixtures, `scipy.io.loadmat`)
319+
- Multi-platform pytest (Windows, Ubuntu, macOS) × Python 3.10-3.13 (12-job matrix)
320+
- Integration tests in `tests/integration/` with `assert_fields_close()` (rtol=1e-10, atol=1e-12)
321+
- Weekly example runner (`run-examples.yml`, `KWAVE_FORCE_CPU=1`)
213322

214-
**Add:**
215-
- `tests/test_native_solver.py` - native vs C++ parity
216-
- `tests/test_unified_api.py` - new kwargs API
217-
- `tests/test_deprecation_warnings.py` - verify warnings emitted
218-
- `tests/test_backend_parity.py` - all backends produce same results
323+
**v0.6.0 (done):**
324+
- `tests/test_native_solver.py` — 33 tests for Python backend
325+
- `tests/test_unified_api.py` — new kwargs API
326+
- `tests/test_compat.py``options_to_kwargs()` migration
327+
328+
**v0.6.1 (C-order migration):**
329+
- `tests/test_memory_layout.py` — C/F-order input produces identical results, `simulate_from_dicts` F→C→F round-trip, `cpp_simulation` writes correct F-order HDF5
330+
331+
**v0.6.2 (example migration):**
332+
- Per-example MATLAB reference integration tests — validate via k-wave-cupy interop first, then add `.mat` fixtures to `tests/integration/`
333+
- Each ported example gets a corresponding `test_<example_name>.py` with MATLAB reference comparison
334+
335+
**v0.6.3 (axisymmetric):**
336+
- Extend existing `test_ivp_axisymmetric_simulation.py` to use new `kspaceFirstOrder(..., axisymmetric=True)` API
337+
- New MATLAB reference tests for `at_circular_piston_AS`, `at_focused_bowl_AS`
338+
339+
**Cross-cutting:**
340+
- `tests/test_backend_parity.py` — Python vs C++ backends produce same results for shared test cases
341+
- `tests/test_Future_warnings.py` — verify FutureWarning emitted on legacy API calls
219342

220343
---
221344

@@ -246,8 +369,8 @@ result = kspaceFirstOrder(kgrid, medium, source, sensor, backend='native')
246369
print('Success:', result['p'].shape)
247370
"
248371

249-
# v0.6.0 - Deprecation warnings
250-
uv run python -W error::DeprecationWarning -c "
372+
# v0.6.0 - Future warnings
373+
uv run python -W error::FutureWarning -c "
251374
from kwave.options.simulation_options import SimulationOptions
252375
" # Should warn
253376

@@ -260,10 +383,13 @@ uv run pytest tests/ -v
260383
## Implementation Order
261384

262385
1. **Now:** Finalize master/main for v0.5.0
263-
2. **Next:** Python solver + `kspaceFirstOrder.py` + deprecation for v0.6.0
264-
3. **Then:** `kwp` CLI for v0.7.0
265-
4. **Then:** Clean delete for v1.0.0
266-
5. **Post-1.0:** Devito, nanobind/MPI based on profiling and user demand
386+
2. **Next:** Python solver + `kspaceFirstOrder()` API + Future for v0.6.0
387+
3. **Then:** C-order migration of helpers/utils for v0.6.1
388+
4. **Then:** Port remaining examples to new API for v0.6.2
389+
5. **Then:** Axisymmetric support in new API for v0.6.3
390+
6. **Then:** `kwp` CLI for v0.7.0
391+
7. **Then:** Clean delete for v1.0.0
392+
8. **Post-1.0:** Devito, nanobind/MPI based on profiling and user demand
267393

268394
---
269395

0 commit comments

Comments
 (0)