Skip to content

feat: Implement GRIN (Gradient-Index) material and propagation#436

Open
zhazhajust wants to merge 8 commits intoHarrisonKramer:masterfrom
zhazhajust:feat/grin-material
Open

feat: Implement GRIN (Gradient-Index) material and propagation#436
zhazhajust wants to merge 8 commits intoHarrisonKramer:masterfrom
zhazhajust:feat/grin-material

Conversation

@zhazhajust
Copy link

@zhazhajust zhazhajust commented Jan 8, 2026

Summary

This PR implements Gradient-Index (GRIN) material support in Optiland, enabling accurate modeling of optical components with spatially varying refractive indices. Open #337

Key Features

1. GRIN Material Implementation

  • New GradientMaterial class in optiland/materials/gradient_material.py
  • Supports arbitrary refractive index profiles n(x, y, z)
  • Built-in profiles: axial, radial, and gradient distributions
  • Extensible API for custom gradient functions

2. GRIN Ray Propagation

  • Enhanced GRIN propagation algorithm in optiland/propagation/grin.py
  • Numerical ray tracing through gradient-index media using 4th-order Runge-Kutta method
  • Bidirectional propagation support (forward and backward)
  • Proper handling of reflections at GRIN material boundaries
  • Automatic ray tracing step adaptation based on gradient strength

3. Comprehensive Testing

  • 269 lines of new tests in tests/propagation/test_grin.py
  • Tests for axial, radial, and spherical gradient profiles
  • Validation of bidirectional propagation with reflections
  • Serialization test coverage

4. Examples and Documentation

  • Detailed implementation guide: GRIN_IMPLEMENTATION_SUMMARY.md
  • Interactive examples:
    • examples/simple_grin_test.py - Basic GRIN lens behavior
    • examples/grin_reflection_detailed.py - Reflection effects in GRIN media

Changes

  • 8 files changed, 1,322 insertions(+), 25 deletions(-)
  • Three commits implementing core functionality, testing, and reflection support

Testing

All existing tests pass, plus new comprehensive GRIN material tests covering:

  • Axial gradient propagation
  • Radial gradient focusing effects
  • Spherical gradient profiles
  • Bidirectional ray tracing with reflections
  • Edge cases and boundary conditions

This implementation enables Optiland to model advanced optical components like GRIN lenses, gradient-index fibers, and other waveguide devices critical in modern optical systems.

Cai Jie and others added 7 commits January 8, 2026 10:01
Add comprehensive support for gradient-index optical materials:

- Add GradientMaterial class with Zemax Gradient3-like profile:
  n(r, z) = n0 + nr2*r² + nr4*r⁴ + nr6*r⁶ + nz1*z + nz2*z² + nz3*z³
  Supports both radial and axial refractive index gradients

- Implement GRINPropagation using RK4 numerical integration:
  Solves ray equation: d/ds(n·dr/ds) = ∇n
  Adaptive step size control for accuracy
  Handles boundary conditions and normalization

- Add comprehensive test suite (9 tests):
  Material initialization and refractive index calculation
  Gradient computation verification
  Straight-line propagation (uniform medium)
  Radial gradient propagation (focusing/defocusing)
  Multi-ray propagation and serialization

- Include usage examples demonstrating:
  Radial GRIN lens (converging/diverging behavior)
  Axial GRIN medium
  Ray path visualization

Test results: ✅ 25/25 propagation tests passing

Closes HarrisonKramer#337
Add comprehensive testing for axial GRIN reflection effect where
refractive index increases with z, causing rays to bend toward
the normal (gradual reflection).

New test cases:
- test_grin_axial_gradient_reflection_effect: Validates that obliquely
  incident rays bend toward z-axis in axial GRIN medium
- test_grin_axial_gradient_strong_reflection: Tests strong gradient
  that creates significant ray bending

Key findings:
- n(z) = 1.5 + 0.05*z over 20mm creates 40% direction change
- Higher incident angles produce more bending
- Rays continuously curve toward higher refractive index

Add visualization example (examples/axial_grin_reflection.py):
- Shows ray paths at different incident angles
- Compares uniform vs GRIN medium behavior
- Demonstrates bending vs incident angle relationship

Test results: ✅ 11/11 GRIN tests passing
Enable GRIN media to handle ray reflection when refractive index
gradient is strong enough to reverse ray direction (N < 0).

Changes:
- Remove N > 0 constraint in GRINPropagation
- Implement adaptive step size for bidirectional propagation
- Add boundary detection for both entrance and exit surfaces
- Allow rays to exit from either surface after reflection

This enables proper modeling of gradual reflection effects in
gradient-index media where rays bend toward higher refractive
index regions until completely reversing direction.
move the description to PR
@HarrisonKramer
Copy link
Owner

Hi @zhazhajust,

Thanks for submitting this! It will be a great addition.

I made some minor changes to the functionality, including updating the OPD calculation. I saw you were using an approximation previously.

One thing that is still missing is making it possible to visualize in 2D and 3D. That will involve making updates to track the (x, y, z) position of points as rays propagate through the GRIN media. I am not certain how best to do this, but I would like to have this functionality before we merge the PR. Do you want to take a shot at it? I can also help here.

Lastly, tracing through a GRIN lens will be inherently slower than standard raytracing. However, I wonder if there are any opportunities for optimization here. The raytrace speed is slower than I expected, but perhaps there's no way around this.

Thanks again,
Kramer

@zhazhajust
Copy link
Author

Hi @HarrisonKramer,

Sorry for the delayed response — I’ve been tied up with a few other things recently.

Thanks for the improvements you made, especially the fix to the OPD calculation. That definitely addressed a weak spot in my original implementation.

For GRIN ray path visualization, here’s the proposed approach I’m planning to take:

Proposed implementation

  • Path recording during GRIN propagation
    Add a record_path option to GRINPropagation that records intermediate (x, y, z) positions at each RK4 integration step.

  • Path storage in RealRays
    Extend RealRays with path-related helpers (e.g. start_path_recording, get_path, has_path) to store per-ray trajectory data.

  • SurfaceGroup integration
    Add a get_ray_paths() method to aggregate ray path data across surfaces.

  • Curved path rendering
    Update the 2D ray visualization in rays.py so rays traversing GRIN media are rendered as continuous curved paths rather than straight segments.

The key idea is that rays propagating through GRIN materials will accumulate position samples during numerical integration, which can then be concatenated across surfaces to visualize the true curved trajectory.

Next steps

  • Verify that the 3D visualization pipeline also supports curved ray paths
  • Add more comprehensive test coverage
  • Treat performance optimizations (e.g. vectorization, adaptive step sizing) as a follow-up once the visualization is in place

Does this direction look reasonable to you? Happy to adjust the approach based on your feedback, or to collaborate on the visualization pieces if that’s helpful.

Thanks again for your input.

@HarrisonKramer
Copy link
Owner

Hi @zhazhajust,

Thanks for your concrete proposal. I agree with your approach, but I would prefer that the ray path recording is optional for GRIN media (and that it defaults to not recording). In general, users won't need the exact (x, y, z) position of rays as they propagate through the GRIN medium, so it should default to saving ray data only on the surface boundaries, as it does now. The visualization code can then trigger the GRIN ray path recording when it traces rays specifically for visualization in 2D/3D. That might just be a simple Boolean flag (perhaps in GRINPropagation?) that the user can also control. Does that make sense? Do you agree with this proposal?

Thanks,
Kramer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants