# Circuit Simulation Reference¶

Simulating circuits using caphe, our flexible and performant circuit solver, consists of two distinct tasks:

• defining the models that caracterise the circuit
• setting up and running a simulation

Defining the models of a PCell is very similar to defining the LayoutView or NetlistView of a PCell. The following is an example of a DirectionalCoupler PCell with a simple CapheModel, the most important method here is _calculate_S:

import ipkiss3.all as i3
class DirectionalCoupler(i3.PCell):
class CapheModel(i3.CapheSModelView):

delta_n_eff = i3.PositiveNumberProperty(default=0.01, doc="difference is effective index between the even and odd supermode of the directional coupler.")

def _calculate_S(self, environment, term1, term2, mode1, mode2):
# calculate your S parameters here
# This function returns a complex-valued number
# based on the environment, terms, and modes.

# Wavelength are part of the environment.
delta_beta = 2 * pi / environment.wavelength * self.delta_n_eff * self.coupler_length

if ((term1.name == 'in1' and term2.name == 'out1') or
(term1.name == 'in2' and term2.name == 'out2') or
(term1.name == 'out1' and term2.name == 'in1') or
(term1.name == 'out2' and term2.name == 'in2')):
# Straight transmission
return 0.5 * (1.0 + exp(1j * delta_beta))

if ((term1.name == 'in1'  and term2.name == 'out2') or
(term1.name == 'in2'  and term2.name == 'out1') or
(term1.name == 'out1' and term2.name == 'in2') or
(term1.name == 'out2' and term2.name == 'in1')):

# Crossing transmission
return 0.5 * (1.0 - exp(1j * delta_beta))

# No reflections, so return 0 in all other cases
return 0


The _calculate_S method models the transmissions from term1 to term2 and it’s called for all possible combinations. This DirectionalCoupler can then be used in a simulation. The following snippet is a simple example of such a simulation.

import ipkiss3.all as i3
import numpy as np
my_dc = DirectionalCoupler(coupler_length=150.0)
my_dc_cm = my_dc.CapheModel(delta_n_eff=0.02) # Using the simple CapheModel
# we create a range of wavelengths
wavelengths =  np.arange(1.3, 1.6, 0.01)
my_engine = i3.CapheFrequencyEngine()

my_simulation = my_engine.SMatrixSimulation(
model=my_dc_cm,
wavelengths=wavelengths
)

# We run the simulation.
my_simulation.run()

# Extract the results from the monitors.
R = my_simulation.monitors['s_matrix']

# print the transmission from the in1 to the out1 term
print(R['in1', 'out1'])