Global Optimization (SHGO)

SHGO stands for Simplicial Homology Global Optimization.

[1]:
from optiland import optic, optimization

Define a starting lens:

[2]:
lens = optic.Optic()

# add surfaces
lens.surfaces.add(index=0, thickness=60)
lens.surfaces.add(index=1, thickness=7, radius=50, material="N-SF2")
lens.surfaces.add(index=2, thickness=15, radius=100)
lens.surfaces.add(index=3, thickness=15, is_stop=True)
lens.surfaces.add(index=4, thickness=7, radius=-85, material="BK7")
lens.surfaces.add(index=5, thickness=100, radius=-66)
lens.surfaces.add(index=6)

# set aperture
lens.set_aperture(aperture_type="EPD", value=15)

# add field
lens.fields.set_type(field_type="angle")
lens.fields.add(y=0)
lens.fields.add(y=10)
lens.fields.add(y=15)

# add wavelength
lens.wavelengths.add(value=0.55, is_primary=True)

# draw lens
lens.draw(num_rays=5)
../../_images/gallery_optimization_shgo_3_0.png

Define optimization problem:

[3]:
problem = optimization.OptimizationProblem()

Add operands (targets for optimization):

[ ]:
# RMS spot size target
for field in lens.fields.get_field_coords():
    input_data = {
        "optic": lens,
        "Hx": field[0],
        "Hy": field[1],
        "surface_number": -1,
        "num_rays": 5,
        "wavelength": 0.55,
        "distribution": "hexapolar",
    }
    problem.add_operand(
        operand_type="rms_spot_size",
        target=0,
        weight=1,
        input_data=input_data,
    )

Define variables - let both radii of curvature of the last lens vary.

[ ]:
for surf_idx in [4, 5]:
    problem.add_variable(
        lens,
        "radius",
        surface_number=surf_idx,
        min_val=-1000,
        max_val=1000,
    )

Check initial merit function value and system properties:

[6]:
problem.info()
╒════╤════════════════════════╤═══════════════════╕
│    │   Merit Function Value │   Improvement (%) │
╞════╪════════════════════════╪═══════════════════╡
│  0 │                229.884 │                 0 │
╘════╧════════════════════════╧═══════════════════╛
╒════╤════════════════╤══════════╤══════════════╤══════════════╤══════════╤═════════╤═════════╤════════════════╕
│    │ Operand Type   │   Target │ Min. Bound   │ Max. Bound   │   Weight │   Value │   Delta │   Contrib. [%] │
╞════╪════════════════╪══════════╪══════════════╪══════════════╪══════════╪═════════╪═════════╪════════════════╡
│  0 │ rms spot size  │        0 │              │              │        1 │   8.777 │   8.777 │          33.51 │
│  1 │ rms spot size  │        0 │              │              │        1 │   8.754 │   8.754 │          33.34 │
│  2 │ rms spot size  │        0 │              │              │        1 │   8.73  │   8.73  │          33.16 │
╘════╧════════════════╧══════════╧══════════════╧══════════════╧══════════╧═════════╧═════════╧════════════════╛
╒════╤═════════════════╤═══════════╤═════════╤══════════════╤══════════════╕
│    │ Variable Type   │   Surface │   Value │   Min. Bound │   Max. Bound │
╞════╪═════════════════╪═══════════╪═════════╪══════════════╪══════════════╡
│  0 │ radius          │         4 │     -85 │        -1000 │         1000 │
│  1 │ radius          │         5 │     -66 │        -1000 │         1000 │
╘════╧═════════════════╧═══════════╧═════════╧══════════════╧══════════════╛

Define optimizer:

[7]:
optimizer = optimization.SHGO(problem)

Run optimization:

[8]:
optimizer.optimize(workers=-1)  # workers=-1 uses all available cores
[8]:
 message: Optimization terminated successfully.
 success: True
     fun: 0.1472372939596464
    funl: [ 1.472e-01]
       x: [ 9.000e+00 -1.323e+00]
      xl: [[ 9.000e+00 -1.323e+00]]
     nit: 1
    nfev: 249
   nlfev: 244
   nljev: 71
   nlhev: 0

Print merit function value and system properties after optimization:

[9]:
problem.info()
╒════╤════════════════════════╤═══════════════════╕
│    │   Merit Function Value │   Improvement (%) │
╞════╪════════════════════════╪═══════════════════╡
│  0 │               0.147237 │            99.936 │
╘════╧════════════════════════╧═══════════════════╛
╒════╤════════════════╤══════════╤══════════════╤══════════════╤══════════╤═════════╤═════════╤════════════════╕
│    │ Operand Type   │   Target │ Min. Bound   │ Max. Bound   │   Weight │   Value │   Delta │   Contrib. [%] │
╞════╪════════════════╪══════════╪══════════════╪══════════════╪══════════╪═════════╪═════════╪════════════════╡
│  0 │ rms spot size  │        0 │              │              │        1 │   0.248 │   0.248 │          41.83 │
│  1 │ rms spot size  │        0 │              │              │        1 │   0.117 │   0.117 │           9.23 │
│  2 │ rms spot size  │        0 │              │              │        1 │   0.268 │   0.268 │          48.94 │
╘════╧════════════════╧══════════╧══════════════╧══════════════╧══════════╧═════════╧═════════╧════════════════╛
╒════╤═════════════════╤═══════════╤═══════════╤══════════════╤══════════════╕
│    │ Variable Type   │   Surface │     Value │   Min. Bound │   Max. Bound │
╞════╪═════════════════╪═══════════╪═══════════╪══════════════╪══════════════╡
│  0 │ radius          │         4 │ 1000      │        -1000 │         1000 │
│  1 │ radius          │         5 │  -32.3104 │        -1000 │         1000 │
╘════╧═════════════════╧═══════════╧═══════════╧══════════════╧══════════════╛

Draw final lens:

[10]:
lens.draw(num_rays=5)
../../_images/gallery_optimization_shgo_19_0.png