Skip to content

feat: #1039 - [E3-F3-P2] Implement to_warp() with manual transfer control#1045

Merged
Gorkowski merged 2 commits intouncscode:mainfrom
Gorkowski:issue-1039-adw-8864132c
Feb 3, 2026
Merged

feat: #1039 - [E3-F3-P2] Implement to_warp() with manual transfer control#1045
Gorkowski merged 2 commits intouncscode:mainfrom
Gorkowski:issue-1039-adw-8864132c

Conversation

@Gorkowski
Copy link
Collaborator

Target Branch: main

Fixes #1039 | Workflow: 8864132c

Summary

Implements to_warp_particle_data() and to_warp_gas_data() functions that transfer CPU-side ParticleData and GasData containers to GPU using NVIDIA Warp arrays. These functions provide explicit control over device selection and copy behavior, enabling long GPU-resident simulations where data stays on GPU across many timesteps without CPU round-trips.

This phase builds on the Warp struct definitions from E3-F3-P1 (#1038), completing the CPU→GPU transfer capability as the entry point for GPU-accelerated simulations.

What Changed

New Components

  • particula/gpu/conversion.py - New module (~240 LOC) containing:

    • _ensure_warp_available() - Helper that validates Warp installation
    • _validate_device() - Helper that validates device strings (cuda, cuda:0, cpu, etc.)
    • to_warp_particle_data() - Transfers ParticleData to GPU with device/copy control
    • to_warp_gas_data() - Transfers GasData to GPU with device/copy/vapor_pressure control
  • particula/gpu/tests/conversion_test.py - Comprehensive test suite (~418 LOC) covering:

    • Basic transfer functionality
    • Shape and value preservation
    • Copy independence (copy=True vs copy=False)
    • Device selection (cpu, invalid device handling)
    • Multi-box scenarios (n_boxes > 1 and n_boxes = 1)
    • Error handling (Warp unavailable, shape mismatches)
    • Module export verification

Modified Components

  • particula/gpu/__init__.py - Added exports for new conversion functions:
    • to_warp_particle_data
    • to_warp_gas_data

How It Works

The conversion functions enable one-time CPU→GPU transfer at simulation start:

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   ParticleData  │────▶│ to_warp_        │────▶│ WarpParticle    │
│   (CPU/NumPy)   │     │ particle_data() │     │ Data (GPU)      │
└─────────────────┘     └─────────────────┘     └─────────────────┘
        │                       │
        │                       ▼
        │               ┌─────────────────┐
        │               │ • Device select │
        │               │ • Copy control  │
        │               │ • Validation    │
        │               └─────────────────┘

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│     GasData     │────▶│ to_warp_        │────▶│   WarpGasData   │
│   (CPU/NumPy)   │     │ gas_data()      │     │     (GPU)       │
└─────────────────┘     └─────────────────┘     └─────────────────┘
        │                       │
        │                       ▼
        │               ┌─────────────────┐
        │               │ • Bool→int32    │
        │               │ • vapor_pressure│
        │               │   (optional)    │
        │               └─────────────────┘

Usage pattern:

from particula.gpu import to_warp_particle_data, to_warp_gas_data

# Transfer data to GPU once
gpu_particles = to_warp_particle_data(particles, device="cuda")
gpu_gas = to_warp_gas_data(gas, device="cuda")

# Run GPU simulation loop (no CPU round-trips)
for _ in range(10000):
    gpu_particles = condensation_step(gpu_particles, gpu_gas, dt)

Implementation Notes

  • Device selection: Supports "cuda", "cuda:0", "cuda:1", "cpu" via wp.get_device() validation
  • Copy behavior:
    • copy=True (default): Uses wp.array() - always copies to device
    • copy=False: Uses wp.from_numpy() - may avoid copy if compatible
  • GasData transformations:
    • name field excluded (strings not GPU-compatible)
    • partitioning converted from bool → int32 (True→1, False→0)
    • vapor_pressure parameter added (defaults to zeros if not provided)
  • Import strategy: Warp imported inside functions for graceful degradation when unavailable
  • Error messages: Clear, actionable messages for missing Warp, invalid device, and shape mismatches

Testing

  • Unit tests: 19 test cases covering all acceptance criteria
  • Test patterns: Uses pytest.importorskip("warp") for graceful skip without Warp
  • Device fallback: All tests use CPU device to ensure CI compatibility
  • Round-trip validation: Values verified via .numpy() comparison
  • Edge cases: Single-box, multi-box, invalid device, shape mismatches

Implement conversion functions for transferring ParticleData and GasData
containers to GPU using NVIDIA Warp arrays. This is phase E3-F3-P2 of the
GPU integration feature.

New functions:
- to_warp_particle_data(): Transfer ParticleData to WarpParticleData
- to_warp_gas_data(): Transfer GasData to WarpGasData with vapor_pressure handling

Key features:
- Device selection support (cuda, cuda:0, cuda:1, cpu)
- Copy parameter for copy vs zero-copy transfer modes
- Proper error handling for unavailable Warp and invalid devices
- Bool to int32 conversion for partitioning field
- Optional vapor_pressure parameter (defaults to zeros)

Closes uncscode#1039

ADW-ID: 8864132c
Remove unused variables and reorder imports to fix lint errors:

- Remove unused n_boxes and n_species variables in test_single_box_gas_data
  (F841 lint fix)
- Reorder TYPE_CHECKING imports alphabetically in conversion.py for
  consistency (isort/ruff format fix)

ADW-ID: 8864132c
@Gorkowski Gorkowski added agent Created or managed by ADW automation blocked Blocked - review required before ADW can process labels Feb 3, 2026
@Gorkowski Gorkowski merged commit cc9ac98 into uncscode:main Feb 3, 2026
7 checks passed
@Gorkowski Gorkowski deleted the issue-1039-adw-8864132c branch February 3, 2026 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Created or managed by ADW automation blocked Blocked - review required before ADW can process

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[E3-F3-P2] Implement to_warp() with manual transfer control

1 participant