Skip to content

Conversation

groberts-flex
Copy link
Contributor

@groberts-flex groberts-flex commented Oct 6, 2025

Connect box face derivatives to evaluate_gradient_at_points in DerivativeInfo so that interpolators can be shared when using inside a GeometryGroup.

Greptile Overview

Updated On: 2025-10-06 19:50:07 UTC

Summary

This PR optimizes the performance of Box geometry derivative computation when used inside a GeometryGroup by refactoring the implementation to leverage the existing `evaluate_gradient_at_points` infrastructure in `DerivativeInfo`. The key changes include:
  • Major refactoring of Box derivative computation: The _derivative_face method in tidy3d/components/geometry/base.py was completely rewritten, removing 380+ lines of complex field integration code and replacing it with a simpler grid-based approach that builds spatial grids and evaluates gradients at specific points.

  • Performance optimization through interpolator sharing: By connecting to the evaluate_gradient_at_points method, the new implementation allows interpolators to be shared when multiple Box geometries are processed together in a GeometryGroup, significantly improving computational efficiency.

  • Code simplification: The refactoring eliminates the need for PEC-specific handling, complex epsilon data management, and manual interpolation logic, making the codebase more maintainable while leveraging existing gradient evaluation frameworks.

  • Comprehensive testing: A new test file was added to validate that the optimized Box gradient implementation produces mathematically equivalent results to the established PolySlab approach across different dimensional configurations (2D and 3D cases).

  • Test cleanup: Obsolete Box-specific test functions were removed since the functionality is now covered by the broader gradient evaluation system.

This change fits into the broader Tidy3D architecture by unifying Box derivative computation with the existing DerivativeInfo framework, enabling better resource sharing and performance optimization when working with multiple geometries in electromagnetic simulations.

Changed Files
Filename Score Overview
CHANGELOG.md 5/5 Added changelog entry documenting the Box derivative performance improvement
tidy3d/components/geometry/base.py 4/5 Major refactoring of Box _derivative_face method to use grid-based approach with evaluate_gradient_at_points
tests/test_components/autograd/numerical/test_autograd_box_polyslab_numerical.py 5/5 New comprehensive test validating Box vs PolySlab gradient equivalence across 2D/3D configurations
tests/test_components/test_geometry.py 4/5 Removed obsolete Box-specific test functions that are no longer needed after refactoring

Confidence score: 4/5

  • This PR appears safe to merge with good performance benefits and comprehensive testing coverage
  • Score reflects the substantial refactoring of core gradient computation logic which requires careful validation
  • Pay close attention to the geometry base module changes and ensure the new grid-based approach handles all edge cases correctly

Sequence Diagram

sequenceDiagram
    participant User
    participant Geometry
    participant DerivativeInfo
    participant Interpolators
    participant GradientEvaluator
    
    User->>Geometry: "_compute_derivatives(derivative_info)"
    Geometry->>DerivativeInfo: "create_interpolators(dtype=GRADIENT_DTYPE_FLOAT)"
    DerivativeInfo->>Interpolators: "create field data interpolators"
    Interpolators-->>DerivativeInfo: "interpolators"
    DerivativeInfo-->>Geometry: "interpolators"
    
    loop For each derivative path
        Geometry->>Geometry: "_derivative_faces(derivative_info)"
        
        loop For min/max faces and axes
            Geometry->>Geometry: "_derivative_face(min_max_index, axis_normal, derivative_info)"
            Geometry->>DerivativeInfo: "evaluate_gradient_at_points(spatial_coords, normals, perps1, perps2, interpolators)"
            DerivativeInfo->>GradientEvaluator: "interpolate fields at points"
            GradientEvaluator->>Interpolators: "get field values"
            Interpolators-->>GradientEvaluator: "field values"
            GradientEvaluator-->>DerivativeInfo: "gradient values"
            DerivativeInfo-->>Geometry: "gradient_at_points"
            Geometry->>Geometry: "sum(integration_weight * gradient_at_points)"
            Geometry-->>Geometry: "vjp_face"
        end
        
        Geometry->>Geometry: "_derivatives_center_size(vjps_faces)"
        Geometry-->>Geometry: "vjps_center_size"
    end
    
    Geometry-->>User: "derivative_map"
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile


print("Overlaps (deg):")
print(f"Box vs. PolySlab Adjoint: {box_polyslab_overlap_deg}")
print(f"Box vs. PolySlab Finite Differnece: {fd_overlap_deg}")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: Typo: 'Differnece' should be 'Difference'

Suggested change
print(f"Box vs. PolySlab Finite Differnece: {fd_overlap_deg}")
print(f"Box vs. PolySlab Finite Difference: {fd_overlap_deg}")
Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/test_components/autograd/numerical/test_autograd_box_polyslab_numerical.py
Line: 395:395

Comment:
**syntax:** Typo: 'Differnece' should be 'Difference'

```suggestion
    print(f"Box vs. PolySlab Finite Difference: {fd_overlap_deg}")
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor

github-actions bot commented Oct 6, 2025

Diff Coverage

Diff: origin/develop...HEAD, staged and unstaged changes

  • tidy3d/components/geometry/base.py (98.3%): Missing lines 2498

Summary

  • Total: 58 lines
  • Missing: 1 line
  • Coverage: 98%

tidy3d/components/geometry/base.py

Lines 2494-2502

  2494 
  2495             is_2d_map.append(np.isclose(extents[axis_idx], 0.0))
  2496 
  2497         if np.all(is_2d_map):
! 2498             return 0.0
  2499 
  2500         is_2d = np.any(is_2d_map)
  2501 
  2502         sim_bounds_normal, sim_bounds_perp = self.pop_axis(

Copy link
Collaborator

@yaugenst-flex yaugenst-flex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+99 / -346 love to see it 😄
Caught some minor issues but overall looks great, thanks @groberts-flex

# permittivity data
eps_xyz = [derivative_info.eps_data[f"eps_{dim}{dim}"] for dim in "xyz"]
if min_max_index == 0:
if coord_normal_face <= derivative_info.simulation_bounds[0][axis_normal]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember we discussed this at some point but I need a refresher 😆 So now we zero gradients for faces that sit at the simulation boundaries, right? It's an edge case, but I feel like these should be strict comparisons?

Comment on lines +2525 to +2527
integration_bounds_perp = (
np.maximum(bounds_perp[nonzero_dim][0], sim_bounds_perp[nonzero_dim][0]),
np.minimum(bounds_perp[nonzero_dim][1], sim_bounds_perp[nonzero_dim][1]),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to check here if the resulting interval is valid. If a box lies completely outside of the domain I think we'd end up with lower > upper here? And then spacing_to_grid_points will create invalid data for the interpolators I think.

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