Porting circuit models and user code from Ipkiss 3.1.2 to Ipkiss 3.1.3
Old and new style circuit models are compatible with each other. More specifically, a circuit can have both CapheSModelView
(old), CapheModelFromNetlist
(old) and CircuitModelView
(new) views. This compatibility allows a smooth transition from the old to the new syntax for defining
compact models.
It is however recommended to move models to the new syntax, for robustness, stability, and ease of use. See the circuitmodel tutorial for more information on how to build new style models.
To port your models and user code, two things need to happen:
Converting the PCell definition
Convert user code (renaming CapheModel to CircuitModel)
1. Convert PCell definition
Below are two of the most common situations that occur when building models, and how the code is converted to the new syntax.
Converting a compact model with an S-matrix
A
CapheSModelView
that defines an S-matrix used to be written as shown below:class MyWaveguide(i3.PCell): class Netlist(i3.NetlistView): def _generate_terms(self, terms): terms += i3.OpticalTerm(name='in') terms += i3.OpticalTerm(name='out') return terms class CapheModel(i3.CapheSModelView): length = i3.PositiveNumberProperty(doc="Waveguide length", default=100) n_eff = i3.PositiveNumberProperty(doc="Effective index", default=2.4) def _calculate_S(self, environment, term1, term2, mode1, mode2): phase = 2 * np.pi / environment.wavelength * self.n_eff * self.length A = 0.99 if term1.name == 'in' and term2.name == 'out': return A * np.exp(1j * phase) if term1.name == 'out' and term2.name == 'in': return A * np.exp(1j * phase) if term1.name == 'in' and term2.name == 'in': return 0 if term1.name == 'out' and term2.name == 'out': return 0
This now becomes:
class MyWaveguideModel(i3.CompactModel): parameters = ['n_eff', 'length'] terms = [i3.OpticalTerm(name='in'), i3.OpticalTerm(name='out')] def calculate_smatrix(parameters, env, S): phase = 2 * np.pi / env.wavelength * parameters.n_eff * parameters.length A = 0.99 S['in', 'out'] = A * np.exp(1j * phase) S['out', 'in'] = A * np.exp(1j * phase) S['in', 'in'] = 0.0 S['out', 'out'] = 0.0 class MyWaveguide(i3.PCell): class Netlist(i3.NetlistView): def _generate_terms(self, terms): terms += i3.OpticalTerm(name='in') terms += i3.OpticalTerm(name='out') return terms class CircuitModel(i3.CircuitModelView): length = i3.PositiveNumberProperty(doc="Waveguide length", default=100) n_eff = i3.PositiveNumberProperty(doc="Effective index", default=2.4) def _generate_model(self): return MyWaveguideModel(length=self.length, n_eff=self.n_eff)
Converting a hierarchical model
A hierarchical model:
class MyCircuit(i3.PCell): class Netlist(i3.NetlistView): # defining the netlist here class CapheModel(i3.CapheModelFromNetlist): pass
Now becomes:
class MyCircuit(i3.PCell): class Netlist(i3.NetlistView): # defining the netlist here class CircuitModel(i3.CircuitModelView): def _generate_model(self): return i3.HierarchicalModel.from_netlistview(self.netlist_view)
2. Convert user code
Once your pcells are converted to the new syntax, you can convert this pattern:
wg_t = WireWaveguideTemplate() wg_t.CapheModel(n_eff=2.4)
Into this pattern:
wg_t = WireWaveguideTemplate() wg_t.CircuitModel(n_eff=2.4)
A find-replace throughout your codebase should be sufficient to do the conversion.