Example-01: Optimizaion (import/export API)

[1]:
# Loading API facilitates (suboptimal) interface with different optimization libraries
# In this example, quadrupole gradients are used to fit beta functions
[2]:
from pathlib import Path

from model.command.external import load_sdds
from model.command.external import load_lattice
from model.command.external import text_lattice

import numpy
from numpy import ndarray as Array

from scipy.optimize import minimize
[3]:
# Set quadrupole gradient and compute and return twiss parameters

def evaluate(knobs:Array) -> Array:
    kf, kd = knobs
    path:Path = Path('optimize.lte')
    lattice:dict[str, dict[str, str | int | float | dict]] = load_lattice(path)
    lattice['QF']['K1'] = float(kf)
    lattice['QD']['K1'] = float(kd)
    with path.open('w') as stream:
        stream.write(text_lattice('LTE', lattice))
    !elegant 'optimize.ele' > /dev/null
    !sddsconvert -ascii 'binary.twiss' 'optimize.twiss'
    path:Path = Path('optimize.twiss')
    _, columns = load_sdds(path)
    return numpy.asarray([[data['betax'], data['betay']] for location, data in columns.items()]).T
[4]:
# Set target beta functions

target:Array = numpy.asarray([+0.21, -0.19])
result:Array = evaluate(target)
[5]:
# Set objetive function to minimize

def objective(knobs:Array) -> Array:
    return numpy.sum((evaluate(knobs) - result)**2)

objective(target)
[5]:
0.0
[6]:
# Optimize

knobs:Array = numpy.asarray([+0.20, -0.20])

minimize(objective, knobs, method='Nelder-Mead')
[6]:
       message: Optimization terminated successfully.
       success: True
        status: 0
           fun: 1.3489521479279302e-28
             x: [ 2.100e-01 -1.900e-01]
           nit: 20
          nfev: 40
 final_simplex: (array([[ 2.100e-01, -1.900e-01],
                       [ 2.100e-01, -1.900e-01],
                       [ 2.100e-01, -1.900e-01]]), array([ 1.349e-28,  2.891e-05,  6.010e-05]))