In this example, we show how an INTERCONNECT time domain simulation can be driven from Python using Lumerical’s Python API. We provide example scripts that show how to use the cosimulation commands runitialize , runstep , setvalue , getvalue and runfinalize to control an INTERCONNECT time domain simulation while setting and getting signal values at desired ports.
Note:
|
Python co-simulation with INTERCONNECT
The problem we consider is a simple optical transceiver that can be operated in a variable speed mode. The setup consists of a CW laser (with RIN of -120 dB/Hz and power of 10 dBm) that feeds an ideal modulator. The light then passes through an attenuator and into a PIN photodiode (PD) where it is converted back to an electric signal. The PD includes a dark current of 0.1 mA and thermal noise of 1e-10 A/sqrt(Hz). The PD is followed by a low pass filter with a cutoff frequency of 10 GHz, to simulate the frequency response of the PD. The output is then forked. One fork is fed to a low pass filter with cutoff frequency of 0.2 GHz which can be used to monitor the optical power arriving at the PD. The second fork is fed to 2 eye diagram monitors – one measuring an eye at 25 GB/s and the other at 10 GB/s.
What is unusual about this setup is that the modulator is being driven by an EDA Cosimulation element . Furthermore, the Cosimulation element is also connected to the output of the monitoring signal, as well as the main output.
The co-simulation can be driven by Lumerical script and/or Python. The code will allow us to design control circuitry that switches the transceiver into operation at 25GB/s if the monitor power shows that the signal arriving on the detector is high enough. We can then look at the dynamics of the transition from 10GB/s operation to 25GB/s operation.
Simulation in Lumerical script
Simulation in Lumerical script
Open the .icp file co_simulation_example.icp with INTERCONNECT and the script file co_simulation_example.lsf . First, set the variable "target_speed" to “low” and run the script. Also, set the attenuator to 10 dB.
The script will plot the driving electrical signal, which is made up of an ideal NRZ signal of bits from a pseudo-random sequence, the signal used to monitor the optical power arriving at the PD and the output from the PD.
Signal driving the ideal modulator |
Monitoring signal |
Output from the PD |
To visualize the eye diagram for the low speed co-simulation, you can go to "EYE_2" and right click and select "display results". The eye diagram is open well and the BER is estimated to be approximately 1e-19.
Next, change the "target_speed" variable to “high” and rerun the script. This will run the same transceiver at 25GB/s. The driving signal and output signal are shown below.
Signal driving the ideal modulator |
Output from the PD |
If we now display the results of the element "EYE_1", recording the eye at 25 GB/s, we see that it is still open, however, the BER is estimated to be about 2.5e-9.
If we change the attenuator to have a loss of 18 dB, we can rerun and now see that the eye is closed.
After analysis of the previous results, we can set our "target_speed" to “variable” and our "conversion_threshold" to 0.0005. Once the monitor signal stays above the conversion threshold for at least the length of one bit, we switch from low speed to high speed.
If we switch the attenuator back to 10 dB, we see the following results.
Signal driving the ideal modulator |
Output from the PD |
Monitoring signal |
The operating speed switches from 10 GB/s to 25 GB/s |
If we view the 25 GB/s eye diagram we can see that the eye is mostly open. The errors come from the early part of the signal where we were operating at only 10 GB/s, so this transition period would be lost communication time.
Simulation in Python
We can repeat everything in Python. To do this, the Python API must be configured and you must have a license. Please see Python API for more details.
For this example, we have used Lumerical script commands driven from Python to display results for easy comparison, but data visualization could be done directly in Python. At the end of the simulation, we pause the Python with pdb.set_trace(). This allows you to use the INTERCONNECT UI to display results before the window is closed. You can observe the simulation runs much more slowly with the Python API than from the Lumerical script, and this is something that Lumerical will be improving in the future.
Bit sequence from Lumerical script |
Bit sequence from Python |
Output signal from Lumerical script |
Output signal from Python |
The differences between the bit sequences are because of a different random number generator. When the co-simulation pauses, we can go to the INTERCONNECT file to visualize the eye diagram. The eye diagram is offset due to the uncertainty in the transition time from 10 GB/s to 25 GB/s operation but it is clearly open.
See also
Setting up Python API, List of commands, Matlab API, Python API, Parameter Sweep