AOI optimization operands detach Torch gradients in standard and batched evaluation · Issue #972 · optiland/optiland · GitHub
Skip to content

AOI optimization operands detach Torch gradients in standard and batched evaluation #972

Closed

Description

@somnus-J-307

At upstream commit 2201ab0d7ac6f88d529dc7ec8444448e674d9a9c, both RayOperand.AOI and the batched evaluator's _extract_aoi convert the computed angle to a Python float with .item(). An AOI-only objective therefore loses its connection to optical variables on the Torch backend.

For a Cooke triplet, tracing the on-axis field at pupil (0, 0.5) to surface 1 gives an AOI of about 6.520933 degrees. Varying its radius gives a finite-difference derivative of about -0.297509 degrees per lens unit, but the optimization residual and merit have requires_grad=False with batching either enabled or disabled.

Minimal reproduction (repeat with batching=False for the standard path):

import optiland.backend as be
import torch
from optiland.optimization import OptimizationProblem
from optiland.samples import CookeTriplet

be.set_backend("torch")
be.set_precision("float64")
lens = CookeTriplet()
problem = OptimizationProblem(batching=True)
problem.add_variable(lens, "radius", surface_number=1)
variable = problem.variables[0].variable
radius = torch.tensor(variable.get_value().item(), dtype=torch.float64,
                      requires_grad=True)
variable.update_value(radius)
problem.update_optics()
problem.add_operand("AOI", target=5.0, input_data=dict(
    optic=lens, surface_number=1, Hx=0.0, Hy=0.0, Px=0.0, Py=0.5,
    wavelength=lens.primary_wavelength,
))
print(problem.residual_vector().requires_grad)  # False before the fix
print(problem.sum_squared().requires_grad)     # False before the fix

Preserving the tensor alone also reveals a NaN derivative from acos(1) for a normal-incidence zero-target merit.

I have prepared a focused fix that keeps a scalar backend value, uses a shared equivalent unsigned atan2 angle calculation for both evaluation paths, and covers the scalar-stacking regression from #352. Local NumPy/Torch tests check ordinary incidence against finite differences and normal-incidence zero-target merit gradients. No new operand or optical convention is introduced.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions