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