Source code for optimization.variable.nurbs

"""This module contains variable classes for NURBS geometries.

This module contains the `NurbsPointsVariable` and `NurbsWeightsVariable`
classes, which represent variables for the control points and weights of a
NurbsGeometry, respectively. These classes inherit from the `VariableBehavior`
class.

Kramer Harrison, 2024
"""

from __future__ import annotations

import contextlib

from optiland import backend as be
from optiland.optimization.variable.base import VariableBehavior


[docs] class NurbsPointsVariable(VariableBehavior): """Represents a variable for a NURBS control point. Args: optic: The optic object associated with the variable. surface_number: The index of the surface in the optical system. coeff_index: The indices of the control point. apply_scaling: Whether to apply scaling to the variable. """ def __init__( self, optic, surface_number, coeff_index, apply_scaling=True, **kwargs, ): super().__init__(optic, surface_number, **kwargs) self.apply_scaling = apply_scaling self.coeff_index = coeff_index
[docs] def get_value(self): """Gets the current value of the control point. Returns: The current value of the control point. """ surf = self._surfaces[self.surface_number] i, j, k = self.coeff_index with contextlib.suppress(IndexError): value = surf.geometry.P[i, j, k] if self.apply_scaling: return self.scale(value) return value
[docs] def update_value(self, new_value): """Updates the value of the control point. Args: new_value: The new value of the control point. """ if self.apply_scaling: new_value = self.inverse_scale(new_value) surf = self.optic.surfaces[self.surface_number] i, j, k = self.coeff_index with contextlib.suppress(IndexError): if be.get_backend() == "torch": p_copy = be.copy(surf.geometry.P) p_copy[i, j, k] = new_value surf.geometry.P = p_copy else: surf.geometry.P[i, j, k] = new_value
[docs] def scale(self, value): """Scales the value of the variable. This can be used for improved optimization performance. Args: value: The value to scale. Returns: The scaled value. """ return value
[docs] def inverse_scale(self, scaled_value): """Inverse scales the value of the variable. Args: scaled_value: The scaled value to inverse scale. Returns: The inverse-scaled value. """ return scaled_value
def __str__(self): """Returns a string representation of the variable. Returns: A string representation of the variable. """ return f"Control Point {self.coeff_index}, Surface {self.surface_number}"
[docs] class NurbsWeightsVariable(VariableBehavior): """Represents a variable for a NURBS weight. Args: optic: The optic object associated with the variable. surface_number: The index of the surface in the optical system. coeff_index: The indices of the weight. apply_scaling: Whether to apply scaling to the variable. """ def __init__( self, optic, surface_number, coeff_index, apply_scaling=True, **kwargs, ): super().__init__(optic, surface_number, **kwargs) self.apply_scaling = apply_scaling self.coeff_index = coeff_index
[docs] def get_value(self): """Gets the current value of the weight. Returns: The current value of the weight. """ surf = self._surfaces[self.surface_number] j, k = self.coeff_index with contextlib.suppress(IndexError): value = surf.geometry.W[j, k] if self.apply_scaling: return self.scale(value) return value
[docs] def update_value(self, new_value): """Updates the value of the weight. Args: new_value: The new value of the weight. """ if self.apply_scaling: new_value = self.inverse_scale(new_value) surf = self.optic.surfaces[self.surface_number] j, k = self.coeff_index with contextlib.suppress(IndexError): if be.get_backend() == "torch": w_copy = be.copy(surf.geometry.W) w_copy[j, k] = new_value surf.geometry.W = w_copy else: surf.geometry.W[j, k] = new_value
[docs] def scale(self, value): """Scales the value of the variable. This can be used for improved optimization performance. Args: value: The value to scale. Returns: The scaled value. """ return value
[docs] def inverse_scale(self, scaled_value): """Inverse scales the value of the variable. Args: scaled_value: The scaled value to inverse scale. Returns: The inverse-scaled value. """ return scaled_value
def __str__(self): """Returns a string representation of the variable. Returns: A string representation of the variable. """ return f"Weight {self.coeff_index}, Surface {self.surface_number}"