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 (( == 'in1' and == 'out1') or
              ( == 'in2' and == 'out2') or
              ( == 'out1' and == 'in1') or
              ( == 'out2' and == 'in2')):
               # Straight transmission
               return 0.5 * (1.0 + exp(1j * delta_beta))

           if (( == 'in1'  and == 'out2') or
               ( == 'in2'  and == 'out1') or
               ( == 'out1' and == 'in2') or
               ( == 'out2' and == '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(

# We run the simulation.

# 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'])