lumopt2.parametrization.parametrization#
Parametrization - A flexible parametrization class that uses a user-defined function to map optimization parameters (‘p’) to Lumerical geometric object properties (‘P’).
This is the most general and flexible way to parametrize a design in LumOpt2. Instead of implementing specific geometric operations (like the ClosedCurve or Topology), you simply provide a function that maps a parameter vector to a dictionary of object properties that will be set in Lumerical.
- Basic Usage Example:
>>> def my_parametrization(params): >>> '''Map 3 parameters to cylinder radii''' >>> return { >>> "cyl0::radius": params[0], >>> "cyl1::radius": params[0]+params[1], >>> "cyl2::radius": params[0]+params[1]+params[2] >>> } >>> >>> parametrization = lmpt.Parametrization( >>> func=my_parametrization, >>> bounds=[(50e-9, 200e-9)] * 3 >>> )
- Example with Mixed Properties:
>>> def mixed_parametrization(params): >>> return { >>> "waveguide::x": params[0], >>> "waveguide::y span": params[1], >>> "coupler::radius": params[2], >>> "coupler::gap": params[3] >>> } >>> >>> parametrization = lmpt.Parametrization( >>> func=mixed_parametrization, >>> bounds=[(-1e-6, 1e-6), (400e-9, 600e-9), (5e-6, 10e-6), (100e-9, 300e-9)], >>> initial_params=[0, 500e-9, 7.5e-6, 200e-9] >>> )
- The property keys should follow Lumerical’s naming convention:
“object_name::property_name”
- For example:
“rect1::x span”
“circle2::radius”
“waveguide::y”
More advanced usage could involve vector-valued properties, e.g., “object::vertices” for the vertices of a polygon:
>>> def four_polygon_parametrization(params):
>>> return {
>>> f"poly{idx}::vertices": anp.array([[0, value], [value, 0],
>>> [0, -value], [-value, 0]])
>>> for idx, value in enumerate(params)}
>>> }
>>>
>>> parametrization = lmpt.Parametrization(
>>> func=four_polygon_parametrization,
>>> bounds=[(100e-9, 300e-9)] * 4,
>>> initial_params=[200e-9] * 4
>>> )
If the mapping function cannot be tracked by autograd, use the flag use_jac=False. This can happen when the mapping function makes use of third-party libraries or custom code that autograd cannot differentiate through.
- Non-differentiable Example:
>>> def nondiff_func_parametrization(params): >>> '''Map 5 parameters to cylinder radii using non-differentiable functions''' >>> return { >>> "cyl0::radius": nondiff_func1(params), >>> "cyl1::radius": nondiff_func2(params), >>> "cyl2::radius": nondiff_func3(params) >>> } >>> >>> parametrization = lmpt.Parametrization( >>> func=nondiff_func_parametrization, >>> bounds=[(50e-9, 200e-9)] * 5, >>> initial_params=[200e-9] * 5, >>> use_jac=False >>> )
In this case, the class will assume that each optimization parameter affects all geometric objects in the optimization region for the purposes of the dEps calculation. This is a more conservative assumption that may lead to less efficient gradient calculations, but allows for maximum flexibility in the parametrization.
Classes#
|
Parametrized geometry using a user-defined function to map parameters. |