Home Forums Nazca Create trial cells when using minimizer algorithm? Reply To: Create trial cells when using minimizer algorithm?

#6444
Ronald
Keymaster

Dear Jon,

The below MZI example in demofab may contain what you are looking for.

A root-solver optimizes the MZI for a specific target geometrical path length difference. The MZI method behaves either like a function to optimize for a path length difference in the root-solver, or it returns a Nazca Cell. In the former case it deletes all cells generated in the call; Particularly related to your question, I create sets S1 and S2 from dict nd.cfg.cellnames just before and just after a cell iteration. This dict is leading in tracking cell warnings etc., and popping the new cells S2 – S1 will make Nazca forget about them.

The example here uses the “trace” module for measuring geometrical interconnect length, but this concept also can be exploited in a more fancy way utilizing the pathfinder module and compact models, which is something that would need dedicated tutorials.

As for your radius question, interconnects do have a build-in minimum radius check option, which is based on the xsection.minimum_radius attribute of the xs you assign to the interconnect.

from functools import partial
from scipy.optimize import fsolve
import nazca as nd
import nazca.demofab as demo

def cell_to_solve(offset=10, target_diff=20, cell=False):
    """Create a temporary MZI cell to return the arm length difference or return the Cell.

    Free parameter here is the sbend offset.

    Args:
        cell (bool): False: return distance from target; True: Return MZI cell.

    Returns:
        Cell | float:
    """
    if not cell:
        S1 = set(nd.cfg.cellnames.keys())
    with nd.Cell('test') as C:
        m1 = demo.mmi1x2_dp().put(0)
        nd.trace.trace_start()
        demo.deep.sbend(offset=offset).put(m1.pin['b0'])
        demo.deep.sbend(offset=-offset).put()
        nd.trace.trace_stop()
        L1 = nd.trace.trace_length()
        m2 = demo.mmi2x2_dp().put()
        nd.trace.trace_start()
        demo.deep.sbend_p2p(pin1=m1.pin['b1'], pin2=m2.pin['a1']).put()
        nd.trace.trace_stop()
        L2 = nd.trace.trace_length()
        diff = L1 - L2
    if cell:
        return C
    else:
        S2 = set(nd.cfg.cellnames.keys())
        for dS in S2 - S1:
            nd.cfg.cellnames.pop(dS)
        return diff - target_diff

def find_MZI_solution(target_diff, initial_offset):
    """Find an optimized offset to reach the target-diff in the MZI using a standard root solver.

    Args:
        target_diff (float): target armlength difference in MZI
        inititial_offset (float): starting offset to find a solution
    """
    func = partial(cell_to_solve, target_diff=target_diff)
    root = fsolve(func, [initial_offset])
    return func(offset=root[0], cell=True)

MZI = find_MZI_solution(target_diff=50, initial_offset=70)
nd.export_png(MZI)

Ronald