### Install Photontorch Development Version Source: https://github.com/flaport/photontorch/blob/master/README.md Clone the repository and install the development version of Photontorch using pip. Includes instructions for Git hooks. ```bash git clone https://git.photontorch.com/photontorch.git ./install-git-hooks.sh # Unix [Linux/Mac/BSD/...] install-git-hooks.bat # Windows pip install -e photontorch ``` -------------------------------- ### Setup Training Environment and Optimizer Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb Configure the simulation environment for frequency domain simulations with gradient tracking enabled. Initialize the Adam optimizer for circuit parameters. ```python # define simualation environment train_env = pt.Environment( wl=1525e-9, # we want minimal transmission at this wavelength freqdomain=True, # we will do frequency domain simulations grad=True, # gradient need to be tracked in order to use gradient descent. ) # define target for the simulation, lets take 0 (ideally no transmission at resonance) target = 0 # let's define an optimizer. # The Adam optimizer is generally considered to be the best # gradient descent optimizer out there: optimizer = torch.optim.Adam(circuit.parameters(), lr=0.1) ``` -------------------------------- ### Install Photontorch Stable Version Source: https://github.com/flaport/photontorch/blob/master/README.md Install the latest stable version of Photontorch using pip. ```bash pip install photontorch ``` -------------------------------- ### Initialize Environment and Source Source: https://github.com/flaport/photontorch/blob/master/examples/07_unitary_matrix_network_in_the_time_domain.ipynb Sets up the simulation environment with parameters like time start, end, step, and wavelength. Defines the input source tensor, ensuring it has named dimensions if less than 4D. ```python N = 4 length = 25e-6 #[m] transmission = 0.5 #[] neff = 2.86 env = pt.Environment( t_start = 0, t_end = 2000e-14, dt = 1e-13, wl = 1.55e-6, ) pt.set_environment(env) source = torch.ones(N, names=["s"])/np.sqrt(N) # Source tensors with less than 4D need to have named dimensions. env ``` -------------------------------- ### Import Libraries and Setup Source: https://github.com/flaport/photontorch/blob/master/examples/07_unitary_matrix_network_in_the_time_domain.ipynb Imports necessary libraries including Photontorch, PyTorch, NumPy, Matplotlib, and tqdm. Configures NumPy for better array printing and sets a random seed for reproducibility. ```python # Photontorch import photontorch as pt # Python import torch import numpy as np import matplotlib.pyplot as plt from tqdm.notebook import trange # numpy settings np.random.seed(6) # seed for random numbers np.set_printoptions(precision=2, suppress=True) # show less numbers while printing numpy arrays ``` -------------------------------- ### Initialize and Inspect Readout Network Source: https://github.com/flaport/photontorch/blob/master/examples/05_optical_readout.ipynb Initializes a Readout network with 4 weights and prints the initial weights. This demonstrates the setup before any training. ```python nw = Readout(4) with pt.Environment(wl=wl0, freqdomain=True): print('weights:') print(' '.join(['%.2f'%w for w in nw.allpasses(source=1)[-1,0,:,0]])) nw.plot(nw(source=1)) plt.xticks([1549,wl0*1e9,1551], [1549,'$\\lambda_0$',1551]); plt.yticks([0.1,1]) plt.grid(True) plt.show() ``` -------------------------------- ### Instantiate AllPass Network Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Creates an instance of the custom AllPass Photontorch network. No specific setup is required beyond defining the class. ```python allpass = AllPass() ``` -------------------------------- ### Instantiate AllPass Network Source: https://github.com/flaport/photontorch/blob/master/examples/01_all_pass_filter.ipynb Creates an instance of the `AllPass` network defined previously. This prepares the network for simulation setup. ```python nw = AllPass() ``` -------------------------------- ### Import Libraries for Photontorch Simulation Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Imports essential libraries including numpy, matplotlib, tqdm, torch, and photontorch. Ensure photontorch is installed via pip. ```python %matplotlib inline import numpy as np import matplotlib.pyplot as plt from tqdm.notebook import tqdm # [pip install tqdm] import torch # [conda install pytorch -c pytorch, only python 3!] import photontorch as pt # [pip install photontorch] my simulation/optimization library ``` -------------------------------- ### Import Libraries for PhotonTorch Simulation Source: https://github.com/flaport/photontorch/blob/master/examples/03_circuit_optimization_by_backpropagation.ipynb Imports necessary libraries including NumPy, Matplotlib, PyTorch, PhotonTorch, and tqdm for progress bars. Ensure these libraries are installed before running. ```python # Python %matplotlib inline import numpy as np import matplotlib.pyplot as plt # Torch import torch # PhotonTorch import photontorch as pt # Progress Bars from tqdm.notebook import tqdm ``` -------------------------------- ### Configure Simulation Environment for Optimization Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Defines the simulation environment for frequency domain analysis with gradient computation enabled. This setup is crucial for optimizing the CROW parameters. ```python train_env = pt.Environment( wavelength = 1e-6*np.linspace(1.53, 1.58, 1001), #[m] freqdomain=True, # we will be doing frequency domain simulations grad=True, # we need to enable gradients to be able to optimize ) ``` -------------------------------- ### Import Libraries and Set Seeds Source: https://github.com/flaport/photontorch/blob/master/examples/08_general_ring_networks.ipynb Imports necessary libraries and sets random seeds for reproducibility. Ensure all required libraries are installed. ```python import torch import numpy as np import matplotlib.pyplot as plt import photontorch as pt from tqdm.notebook import trange torch.manual_seed(42) np.random.seed(33) ``` -------------------------------- ### Define Photontorch Networks Source: https://context7.com/flaport/photontorch/llms.txt Create custom photonic circuits by subclassing pt.Network, defining components, and linking their ports. This example shows an AllPass filter and a complete circuit with source and detector. ```python import photontorch as pt # Define an all-pass filter network class AllPass(pt.Network): def __init__(self, length=1e-5, neff=2.34, ng=3.4, loss=1000): super(AllPass, self).__init__() self.wg = pt.Waveguide(length=length, neff=neff, ng=ng, loss=loss, trainable=True) self.dc = pt.DirectionalCoupler(coupling=0.3, trainable=True) # Link port 2 of dc -> port 0 of wg -> port 1 of wg -> port 3 of dc self.link("dc:2", "0:wg:1", "3:dc") # Define a complete circuit with source and detector class Circuit(pt.Network): def __init__(self, length=1e-5, neff=2.34, ng=3.4, loss=1000): super(Circuit, self).__init__() self.allpass = AllPass(length, neff, ng, loss) self.source = pt.Source() self.detector = pt.Detector() # Link source -> allpass filter -> detector self.link("source:0", "0:allpass:1", "0:detector") # Create circuit instance circuit = Circuit(length=1.2e-5, neff=2.84, ng=3.2, loss=3e4) ``` -------------------------------- ### Set Up and Run Photontorch Simulation Environment Source: https://github.com/flaport/photontorch/blob/master/examples/01_all_pass_filter.ipynb Configures the simulation environment with specific parameters like wavelength and time steps, then sets this environment globally. Finally, it runs the simulation for the instantiated network. ```python # create environment environment = pt.Environment( wl=np.mean(wavelengths), t=time, ) # set environment pt.set_environment(environment) # run simulation detected = nw(source=1) ``` -------------------------------- ### Initialize Photontorch Environment Source: https://github.com/flaport/photontorch/blob/master/examples/06_unitary_matrix_network_in_the_frequency_domain.ipynb Sets up the matplotlib backend, device, random seeds, and initializes the photontorch environment for frequency domain computations with gradient enabled. ```python %matplotlib inline DEVICE = 'cpu' np.random.seed(0) torch.manual_seed(0) np.set_printoptions(precision=2, suppress=True) env = pt.Environment(freqdomain=True, num_t=1, grad=True) pt.set_environment(env); pt.current_environment() ``` -------------------------------- ### Get Current Environment in PhotonTorch Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Retrieves the current simulation environment object from PhotonTorch. This object contains global simulation parameters. ```python pt.current_environment() ``` -------------------------------- ### Configure Photontorch Environments Source: https://context7.com/flaport/photontorch/llms.txt Set up simulation parameters like wavelength, time steps, and gradient tracking. Environments are immutable after creation and can be used as context managers or set globally. ```python import photontorch as pt import numpy as np # Create a frequency domain environment for wavelength sweep freq_env = pt.Environment( wl=1e-6 * np.linspace(1.45, 1.65, 1000), # Wavelength array in meters freqdomain=True # Enable frequency domain simulation ) # Create a time domain environment time_env = pt.Environment( dt=1e-14, # Time step in seconds t1=2.5e-12, # End time in seconds wl=1.55e-6, # Single wavelength bitrate=40e9, # Bit rate for signal processing samplerate=160e9 # Sample rate ) # Create environment with gradient tracking for training train_env = pt.Environment( wl=1.55e-6, freqdomain=True, grad=True # Enable gradient tracking for optimization ) # Use environment as context manager with freq_env: # Simulation code here pass # Or set environment globally pt.set_environment(time_env) ``` -------------------------------- ### Initialize Adam Optimizer using .parameters() Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Demonstrates an alternative way to initialize the Adam optimizer by using the `.parameters()` method to include all optimizable parameters of the network. ```python optimizer = torch.optim.Adam(allpass.parameters(), lr=0.03) ``` -------------------------------- ### Set Up Photontorch Simulation Environment Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Configures the Photontorch simulation environment for frequency domain analysis. This includes setting the wavelength range and enabling frequency domain simulation. ```python # define the simulation environment: env = pt.Environment( wavelength = 1e-6*np.linspace(1.50, 1.6, 1001), #[m] freqdomain=True, # we will be doing frequency domain simulations ) # set the global simulation environment: pt.set_environment(env) ``` -------------------------------- ### Configure PhotonTorch Environment Source: https://github.com/flaport/photontorch/blob/master/examples/08_general_ring_networks.ipynb Sets up the simulation environment with specific time step, duration, and wavelength range. This configuration is crucial for accurate simulations. ```python env = pt.Environment( dt = 1e-14, t_end=2000e-14, wl=1e-6*np.linspace(1.5, 1.6, 1000), ) env ``` -------------------------------- ### Configure Simulation Environment Source: https://github.com/flaport/photontorch/blob/master/examples/05_optical_readout.ipynb Sets up simulation parameters including CUDA availability, bitrate, time step, sampling rate, output angles, power, latencies, and number of bits. Initializes the photontorch environment with a specified wavelength range and sets it as the global environment. ```python cuda = torch.cuda.is_available() bitrate = 50e9 # bps dt = 1e-14 # new sampling timestep samplerate = 1/dt # new sampling rate angles = np.pi*np.array([0.5,0,-0.5,-0.5,-0.5,1,1]) # output angles of the output waveguides power = 1e-3 #[W] latencies = np.arange(0.01,2.5,0.1) num_bits = 500 c = 299792458.0 #[m/s] speed of light neff = 2.86 # effective index ng = 3.0 # group index of waveguide wl0 = 1.55e-6 # Set global environment environment = pt.Environment( wl=np.linspace(1.549e-6,1.551e-6,10000), freqdomain=True, ) pt.set_environment(environment); pt.current_environment() ``` -------------------------------- ### Frequency Domain Simulation with Context Manager Source: https://github.com/flaport/photontorch/blob/master/examples/01_all_pass_filter.ipynb Sets up and runs a frequency domain simulation using a context manager. This ensures the environment is properly closed after use. The `freqdomain=True` flag is used. ```python # create simulation environment with pt.Environment(wl=wavelengths, freqdomain=True) as env: detected = nw(source=1) print("This was detected inside the context manager:\n""We see an exact copy of the analytically predicted response, as is to be expected") nw.plot(detected, label="simulation") plt.plot(env.wavelength*1e9, detected_target, linestyle="dotted", linewidth=3, label="analytical") plt.legend() plt.show() ``` -------------------------------- ### Create a Photontorch Waveguide Source: https://context7.com/flaport/photontorch/llms.txt Instantiate a Waveguide component with physical parameters like length, loss, effective index, and group index. The phase parameter can be made trainable. ```python import photontorch as pt # Create a waveguide with physical parameters waveguide = pt.Waveguide( length=1e-5, # Length in meters loss=0, # Loss in dB/m neff=2.34, # Effective index wl0=1.55e-6, # Center wavelength for neff definition ng=3.40, # Group index phase=0, # Additional phase correction trainable=True # Make phase parameter trainable ) # Port configuration: # 0 ---- 1 ``` -------------------------------- ### Interactive CROW Plotting with ipywidgets Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Provides an interactive way to visualize CROW filter responses by adjusting the number of rings using an IntSlider. This requires the ipywidgets library to be installed and used in an environment like a Jupyter notebook. ```python from ipywidgets import interact, IntSlider @interact(num_rings=IntSlider(min=1, max=10, step=1)) def plot_detected(num_rings=5): crow = Crow(num_rings=num_rings) detected = crow(source=1) crow.plot(detected) plt.show() ``` -------------------------------- ### Perform a time-domain simulation Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb Sets up a time-domain simulation environment using `pt.Environment` with specified time step (`dt`), total time (`t1`), and wavelength (`wl`). A time-dependent source is created, and the simulation is performed and plotted. ```python # create simulation environment env = pt.Environment(dt=1e-15, t1=2.5e-12, wl=1.55e-6) # create time-dependent source single_source = torch.tensor(np.sin(env.time*5e13), dtype=torch.float32, names=["t"]) # lower dimensional source should have named dimensions. with env: # perform simulation detected = circuit(source=single_source) # plot detected power circuit.plot(detected); plt.show() ``` -------------------------------- ### Perform a frequency-domain simulation Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb Sets up a frequency-domain simulation environment using `pt.Environment` and performs a simulation on the `circuit` instance. The detected power is then plotted. ```python # create simulation environment freq_env = pt.Environment( wl=1e-6*np.linspace(1.45, 1.65, 1000), freqdomain=True ) with freq_env: # perform simulation detected = circuit(source=1) # constant source with amplitude 1 # plot detected power circuit.plot(detected); plt.show() ``` -------------------------------- ### Set Up Optimizer and Loss Function Source: https://github.com/flaport/photontorch/blob/master/examples/03_circuit_optimization_by_backpropagation.ipynb Initializes the Mean Squared Error loss function and the Adam optimizer for training the network parameters. The learning rate is set to 0.2. ```python num_epochs = 10 # number of training cycles learning_rate = 0.2 # multiplication factor for the gradients during optimization. lossfunc = torch.nn.MSELoss() optimizer = torch.optim.Adam(nw.parameters(), learning_rate) ``` -------------------------------- ### Create Source, Detector, and Term Components Source: https://context7.com/flaport/photontorch/llms.txt Initializes basic optical components for injecting power (Source), measuring power (Detector), and absorbing power (Term). ```python import photontorch as pt # Create a source (injects power) source = pt.Source() # Single port: --0 # Create a detector (measures power) detector = pt.Detector() # Single port: --0 # Create a termination (absorbs power without detection) term = pt.Term() # Single port: --0 ``` -------------------------------- ### Create MZI Component Source: https://context7.com/flaport/photontorch/llms.txt Instantiates a Mach-Zehnder Interferometer (MZI) component with specified optical properties and trainability. ```python import photontorch as pt import numpy as np mzi = pt.Mzi( phi=0, # Input phase theta=np.pi / 4, # Phase difference between arms neff=2.34, # Effective index ng=3.40, # Group index wl0=1.55e-6, # Center wavelength length=1e-5, # Waveguide length in meters loss=0, # Loss in dB/m trainable=True # Make phi and theta trainable ) ``` -------------------------------- ### Model a Realistic Photodetector Source: https://context7.com/flaport/photontorch/llms.txt Initializes a `Photodetector` with realistic parameters for simulating optical-to-electrical conversion, including noise. ```python import photontorch as pt from photontorch.detectors import Photodetector # Create photodetector with realistic parameters detector = Photodetector( bitrate=40e9, # Data rate [1/s] samplerate=160e9, # Sample rate [1/s] cutoff_frequency=20e9, # Cutoff frequency [1/s] responsivity=1.0, # Responsivity [A/W] dark_current=1e-10, # Dark current [A] load_resistance=166, # Load resistance [Ohm] filter_order=4, # Butterworth filter order seed=42 # Random seed for noise ) # Use in simulation env = pt.Environment(dt=1e-14, t1=1e-11, wl=1.55e-6, bitrate=40e9, samplerate=160e9) with env: optical_signal = circuit(source=1) electrical_signal = detector(optical_signal) ``` -------------------------------- ### Create Frequency Domain Environment with Gradient Tracking Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Defines a Photontorch environment for frequency domain simulations at a single wavelength, enabling gradient tracking for optimization. ```python train_env = pt.Environment( wl=1.55e-6, #[m] freqdomain=True, # we will be doing frequency domain simulations grad=True, # allow gradient tracking ) ``` -------------------------------- ### Initialize CROW for Optimization on CUDA Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Sets up a CROW instance with 10 rings and prepares it for computation on a CUDA-enabled device. This is a prerequisite for performing gradient-based optimization. ```python device = 'cuda' # 'cpu' or 'cuda' crow = crow = Crow(num_rings=10, random_parameters=False).to(device) ``` -------------------------------- ### Create and Plot Ring Network (Time Domain) Source: https://github.com/flaport/photontorch/blob/master/examples/08_general_ring_networks.ipynb Initializes a RingNetwork with specified parameters, terminates it with sources and detectors, and plots the detected signals in the time domain. Ensure the environment is copied with a specific wavelength for this simulation. ```python nw = pt.RingNetwork( N=2, capacity = 3, wg_factory = lambda: pt.Waveguide(length=50e-6/2, neff=2.86), mzi_factory = lambda: pt.DirectionalCoupler(coupling=0.3), ).terminate([pt.Source("term_in"), pt.Detector("term_pass"), pt.Detector("term_drop"), pt.Detector("term_add")]) with env.copy(wl=env.wavelength.mean()): detected = nw(source=1) nw.plot(detected) plt.show() ``` -------------------------------- ### Simulate with Time-Dependent Source Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb Simulate a circuit using a time-dependent source and plot the detected signal. Ensure the environment is set up correctly. ```python with env: detected = circuit(source=double_source) circuit.plot(detected) plt.show() ``` -------------------------------- ### Enable CUDA Acceleration for Circuits Source: https://context7.com/flaport/photontorch/llms.txt Shows how to move a Photontorch circuit to a CUDA-enabled GPU for accelerated computation and check its device status. ```python import photontorch as pt circuit = Circuit(length=1.2e-5, neff=2.84, ng=3.2, loss=3e4) # Move to GPU circuit = circuit.cuda() # or circuit.cuda(0) for specific device # Check if on GPU print(circuit.is_cuda) # True # Move back to CPU circuit = circuit.cpu() ``` -------------------------------- ### Import Libraries for Photon-Torch Simulation Source: https://github.com/flaport/photontorch/blob/master/examples/02_add_drop_filter.ipynb Imports necessary libraries including numpy for numerical operations, matplotlib for plotting, and photontorch for photonic circuit simulation. ```python %matplotlib inline import numpy as np import matplotlib.pyplot as plt import photontorch as pt ``` -------------------------------- ### Training Loop with Context Manager Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Performs a training loop using a context manager to temporarily apply a specific environment. Includes zeroing gradients, calculating loss, and updating parameters. ```python with train_env: # temporarily override the global environment # we train for 400 training steps for i in tqdm(range(400)): optimizer.zero_grad() # set all the gradients to zero result = torch.squeeze(allpass(source=1)) # squeeze: 4D -> 0D loss = lossfunc(result, target) # MSE loss loss.backward() # calculate the gradients optimizer.step() # use the calculated gradients to perform an optimization step ``` -------------------------------- ### Import Libraries for Photonic Simulation Source: https://github.com/flaport/photontorch/blob/master/examples/09_XOR_task_with_MZI.ipynb Imports necessary libraries including torch, numpy, photontorch, matplotlib, ipywidgets, and tqdm for simulation and visualization. ```python import torch import numpy as np import photontorch as pt import matplotlib.pyplot as plt from ipywidgets import interact from tqdm.notebook import trange ``` -------------------------------- ### Define Simulation Parameters Source: https://github.com/flaport/photontorch/blob/master/examples/03_circuit_optimization_by_backpropagation.ipynb Sets up physical and temporal parameters for the simulation, including effective refractive index, wavelength, time step, and total simulation time. These values are crucial for accurate optical simulations. ```python neff = np.sqrt(12.1) wl = 1.55e-6 dt = 0.5e-9 total_time = 2e-6 time = np.arange(0,total_time,dt) ``` -------------------------------- ### Define Simulation and Design Parameters Source: https://github.com/flaport/photontorch/blob/master/examples/02_add_drop_filter.ipynb Sets up parameters for time-domain simulation and optical design, including time step, total simulation time, speed of light, ring length, and transmission. ```python dt = 1e-14 #[s] total_time = 2000*dt #[s] time = np.arange(0, total_time, dt) c = 299792458 #[m/s] ring_length = 50e-6 #[m] transmission = 0.7 #[] wavelengths = 1e-6*np.linspace(1.50, 1.6, 1000) #[m] ``` -------------------------------- ### Instantiate ReckNxN Network Source: https://github.com/flaport/photontorch/blob/master/examples/07_unitary_matrix_network_in_the_time_domain.ipynb Creates a ReckNxN network with specified dimensions and factories for waveguides and MZIs. The network is terminated to handle boundary conditions. ```python nw = pt.ReckNxN( N=N, wg_factory=lambda: pt.Waveguide(length=1e-4, phase=2*np.pi*np.random.rand(), trainable=True), mzi_factory=lambda: pt.Mzi(length=1e-4, phi=2*np.pi*np.random.rand(), theta=2*np.pi*np.random.rand(), trainable=True), ).terminate() ``` -------------------------------- ### Initialize Adam Optimizer for Phase and Coupling Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Initializes an Adam optimizer to adjust both the phase and coupling parameters of the device. ```python # let's just optimize both the phase and the coupling optimizer = torch.optim.Adam([allpass.wg.phase, allpass.dc.parameter], lr=0.03) ``` -------------------------------- ### Instantiate a circuit with specific parameters Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb Creates an instance of the `Circuit` network with custom parameters for length, effective refractive index (neff), group index (ng), and loss. ```python circuit = Circuit(length=1.2e-5, neff=2.84, ng=3.2, loss=3e4) ``` -------------------------------- ### Instantiate and Plot a CROW Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Demonstrates how to create a CROW instance with a specified number of rings, simulate its response, and plot the detected output. Ensure matplotlib.pyplot is imported as plt. ```python crow = Crow(num_rings=1) detected = crow(source=1) crow.plot(detected) plt.show() ``` -------------------------------- ### Create a Simple Add-Drop Filter Network Source: https://github.com/flaport/photontorch/blob/master/examples/02_add_drop_filter.ipynb Constructs a simple add-drop filter network using Photon-Torch's Network context manager. This approach avoids boilerplate code for network creation. ```python with pt.Network() as nw: nw.term_in = pt.Source() nw.term_pass = nw.term_add = nw.term_drop = pt.Detector() nw.dc1 = nw.dc2 = pt.DirectionalCoupler(1-transmission) nw.wg1 = nw.wg2 = pt.Waveguide(0.5*ring_length, loss=0, neff=2.86) nw.link('term_in:0', '0:dc1:2', '0:wg1:1', '1:dc2:3', '0:term_drop') nw.link('term_pass:0', '1:dc1:3', '0:wg2:1', '0:dc2:2', '0:term_add') ``` -------------------------------- ### Define Simulation and Design Parameters Source: https://github.com/flaport/photontorch/blob/master/examples/01_all_pass_filter.ipynb Sets up key parameters for the all-pass filter simulation, including timestep, total simulation time, loss, effective index, waveguide length, coupler transmission, and wavelengths for sweeping. ```python dt = 1e-14 # Timestep of the simulation total_time = 2.5e-12 # Total time to simulate time = np.arange(0, total_time, dt) # Total time array loss = 1 # [dB] (alpha) roundtrip loss in ring neff = 2.34 # Effective index of the waveguides ng = 3.4 ring_length = 1e-5 #[m] Length of the ring transmission = 0.5 #[] transmission of directional coupler wavelengths = 1e-6*np.linspace(1.5,1.6,1000) #[m] Wavelengths to sweep over ``` -------------------------------- ### NxN Unitary Matrix (Clements) Network Creation Source: https://github.com/flaport/photontorch/blob/master/examples/06_unitary_matrix_network_in_the_frequency_domain.ipynb Creates NxN unitary matrix networks using the Clements decomposition with specified dimensions. Requires Photontorch library and a DEVICE object. Includes initialization and termination steps. ```python clem5x5 = pt.ClementsNxN(N=5).to(DEVICE).terminate().initialize() clem6x6 = pt.ClementsNxN(N=6).to(DEVICE).terminate().initialize() # quick monkeypatch to have the same behavior as the classes defined above clem5x5.__class__ = clem6x6.__class__ = Network ``` -------------------------------- ### Simulate and Plot Initial Response of Multiple All-Pass Filters Source: https://github.com/flaport/photontorch/blob/master/examples/05_optical_readout.ipynb Instantiates a network with four AllPass filters and simulates their combined response. The resulting transmission spectrum is then plotted. ```python nw = MultipleAllPasses(4) nw.plot(nw(source=1)) plt.xticks([1549,wl0*1e9,1551], [1549,'$\\lambda_0$',1551]); plt.yticks([0.1,1]) plt.grid(True) plt.show() ``` -------------------------------- ### Create Time Domain Simulation Environment Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Defines a Photontorch environment for time domain simulations across multiple wavelengths. Specifies the time vector and wavelength list. ```python # define the simulation environment: time_domain_env = pt.Environment( time = np.linspace(0, 1e-11, 1000), wavelength = [1.547e-6, 1.550e-6, 1.560e-6], #[m] freqdomain=False, # we will be doing a time domain simulation ) ``` -------------------------------- ### Utilize Specialized Loss Functions Source: https://context7.com/flaport/photontorch/llms.txt Demonstrates the use of `MSELoss` and `BERLoss` for training, which include latency and warmup handling. ```python import photontorch as pt from photontorch.nn import MSELoss, BERLoss # Mean Squared Error Loss mse_loss = MSELoss( latency=0.5, # Latency in bits warmup=2, # Warmup bits to ignore bitrate=40e9, samplerate=160e9 ) # Bit Error Rate Loss (non-differentiable) ber_loss = BERLoss( threshold=0.5, # Decision threshold latency=0.5, warmup=2, bitrate=40e9, samplerate=160e9 ) # Usage in training loss = mse_loss(prediction, target) ber = ber_loss(prediction, target) ``` -------------------------------- ### Create and Simulate a Ring Network Source: https://context7.com/flaport/photontorch/llms.txt Defines a ring network with a specified number of waveguides and MZI layers, then terminates and simulates it within an environment. ```python ring = pt.RingNetwork( N=4, # Number of input/output waveguides (must be even) capacity=2 # Number of consecutive MZI layers ) # Terminate and simulate ring_circuit = ring.terminate() env = pt.Environment(wl=1.55e-6, freqdomain=True) with env: detected = ring_circuit(source=1) ``` -------------------------------- ### NxN Unitary Matrix (Reck) Network Creation Source: https://github.com/flaport/photontorch/blob/master/examples/06_unitary_matrix_network_in_the_frequency_domain.ipynb Creates NxN unitary matrix networks using the Reck decomposition with specified dimensions. Requires Photontorch library and a DEVICE object. Includes initialization and termination steps. ```python reck2x2 = pt.ReckNxN(N=2).to(DEVICE).terminate().initialize() reck5x5 = pt.ReckNxN(N=5).to(DEVICE).terminate().initialize() # quick monkeypatch to have the same behavior as the classes defined above reck5x5.__class__ = Network ``` -------------------------------- ### Photontorch Utility Functions Source: https://github.com/flaport/photontorch/blob/master/examples/06_unitary_matrix_network_in_the_frequency_domain.ipynb Provides utility functions for converting between PyTorch tensors and NumPy arrays, generating random phases, and creating unitary matrices. These are essential for setting up and manipulating quantum optical circuits. ```python def array(tensor): arr = tensor.data.cpu().numpy() if arr.shape[0] == 2: arr = arr[0] + 1j * arr[1] return arr def tensor(array): if array.dtype == np.complex64 or array.dtype == np.complex128: array = np.stack([np.real(array), np.imag(array)]) return torch.tensor(array, dtype=torch.get_default_dtype(), device=DEVICE) def rand_phase(): return float(2*np.pi*np.random.rand()) ``` ```python def unitary_matrix(m,n): real_part = np.random.rand(m,n) imag_part = np.random.rand(m,n) complex_matrix = real_part + 1j*imag_part if m >= n: unitary_matrix, _, _ = np.linalg.svd(complex_matrix, full_matrices = False) else: _, _, unitary_matrix = np.linalg.svd(complex_matrix, full_matrices = False) return unitary_matrix ``` -------------------------------- ### Import Libraries and Set Seeds Source: https://github.com/flaport/photontorch/blob/master/examples/05_optical_readout.ipynb Imports necessary libraries for numerical computation, plotting, and photontorch. Sets random seeds for reproducibility. ```python import torch import numpy as np import matplotlib.pyplot as plt from tqdm.notebook import tqdm, trange from numpy.fft import fft, ifft, fftfreq from scipy.signal import butter, lfilter import photontorch as pt torch.manual_seed(33) np.random.seed(34) ``` -------------------------------- ### Define Physical and Simulation Parameters Source: https://github.com/flaport/photontorch/blob/master/examples/09_XOR_task_with_MZI.ipynb Sets up physical constants like the speed of light, bitrate, and cutoff frequency, along with simulation parameters such as effective index, number of bits, and seeds for reproducibility. It also defines the default device and data type. ```python c = 299792458.0 #[m/s] speed of light Rb = 20e9 #[1/s] bitrate Rs = 320e9 #[1/s] samplerate fc = 20e9 #[1/s] cutoff frequency for bit generation wl0 = 1550e-9 #[m] center wavelength neff = 2.34 #[1] effective index ng = 3.4 #[1] group index N = 100 #[1] number of bits per bit stream B = 10 #[1] number of bit streams in training batch Str, Sva, Ste = (1, 2, 3) #[1] train seed, validation seed, test seed Lr = (1/Rb) * (c/ng) #[m] reference length (distance the signal travels during one bit period) device = torch.device("cpu") # default device used torch.set_default_dtype(torch.float32) # default dtype used torch.manual_seed(123) # pytorch seed np.random.seed(42) # numpy seed ``` -------------------------------- ### Ring Network Creation Source: https://context7.com/flaport/photontorch/llms.txt Demonstrates the creation of a ring network by modifying MZI orientations within a Clements-like structure. ```python import photontorch as pt ``` -------------------------------- ### Simulate Multiple Wavelengths Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb Simulate a circuit with multiple wavelengths defined in the environment. A constant source with amplitude 1 is used. ```python with env.copy(wl=[1.545e-6, 1.55e-6, 1.56e-6]): detected = circuit(source=1) # constant source with amplitude 1 circuit.plot(detected) plt.show() ``` -------------------------------- ### Initialize Adam Optimizer for Phase Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Initializes an Adam optimizer to adjust the phase parameter of a component. Ensure the learning rate is appropriate to avoid long optimization times. ```python optimizer = torch.optim.Adam([allpass.wg.phase], lr=0.03) # let's just optimize the phase of the ring ``` -------------------------------- ### View Optimization Results Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb After training, simulate the circuit again with the optimized parameters and plot the detected signal. This helps visualize the effect of the optimization. ```python # view result with freq_env: detected = circuit(source=1) # constant source with amplitude 1 circuit.plot(detected) plt.show() ``` -------------------------------- ### Simulate Simple Add-Drop Filter in Time Domain Source: https://github.com/flaport/photontorch/blob/master/examples/02_add_drop_filter.ipynb Runs a time-domain simulation of the simple add-drop filter. The simulation uses a mean wavelength and the defined time array. Results are plotted. ```python with pt.Environment(wl=np.mean(wavelengths), t=time): detected = nw(source=1) nw.plot(detected); ``` -------------------------------- ### Training Loop Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Executes a training loop for 150 steps, optimizing the 'crow' model using the Adam optimizer. It calculates loss using MSE and updates model parameters. Requires 'tqdm' for progress visualization. ```python range_ = tqdm(range(150)) # we train for 150 training steps with train_env: # temporarily override the global environment for i in range_: crow.initialize() optimizer.zero_grad() # set all the gradients to zero result = crow(source=1)[0,:,0,0] # single timestep, all wls, (drop detector=0; through detector=2), single batch loss = lossfunc(result, target) # MSE loss loss.backward() # calculate the gradients optimizer.step() # use the calculated gradients to perform an optimization step range_.set_postfix(loss=loss.item()) print("loss: %.5f"%loss.item()) ``` -------------------------------- ### Initialize Loss Functions Source: https://github.com/flaport/photontorch/blob/master/examples/09_XOR_task_with_MZI.ipynb Initializes Mean Squared Error (MSE) and Bit Error Rate (BER) loss functions with specified latency, threshold, and simulation parameters. These will be used during the training process. ```python mse = pt.MSELoss(latency=1.0, warmup=0.0, bitrate=Rb, samplerate=Rs) ber = pt.BERLoss(latency=1.0, threshold=0.5, warmup=0.0, bitrate=Rb, samplerate=Rs) ``` -------------------------------- ### Define Optimizer Parameters Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Provides a comment explaining the requirements for defining a PyTorch optimizer, specifically mentioning the need for parameters to optimize and a learning rate. It suggests Adam as a good default choice. ```python # to define an optimizer, one needs to provide the parameters to optimize # and the learning rate of the optimizer. # the learning rate is an important parameter that needs to be tuned manually to # the right value. A too large learning rate will result in an optimizer that cannot find the loss ``` -------------------------------- ### Create and Plot Ring Network (Frequency Domain) Source: https://github.com/flaport/photontorch/blob/master/examples/08_general_ring_networks.ipynb Simulates and plots the RingNetwork's response in the frequency domain. This requires copying the environment with the 'freqdomain' flag set to True. ```python with env.copy(freqdomain=True): detected = nw(source=1) nw.plot(detected) plt.show() ``` -------------------------------- ### Time Domain Simulation Source: https://context7.com/flaport/photontorch/llms.txt Simulates the dynamic propagation of optical signals through a circuit using a time-dependent source. Requires torch and matplotlib. ```python import photontorch as pt import torch import numpy as np import matplotlib.pyplot as plt circuit = Circuit(length=1.2e-5, neff=2.84, ng=3.2, loss=3e4) # Create time domain environment env = pt.Environment(dt=1e-15, t1=2.5e-12, wl=1.55e-6) # Create time-dependent source signal source_signal = torch.tensor( np.sin(env.time * 5e13), dtype=torch.float32, names=["t"] # Named dimension for time ) with env: # Perform time domain simulation detected = circuit(source=source_signal) # Plot detected power vs time circuit.plot(detected) plt.xlabel('Time') plt.ylabel('Power') plt.show() ``` -------------------------------- ### Import Libraries for Photontorch Source: https://github.com/flaport/photontorch/blob/master/examples/06_unitary_matrix_network_in_the_frequency_domain.ipynb Imports necessary standard libraries, photontorch, and other utilities like numpy and matplotlib for frequency domain operations. ```python # standard library from collections import OrderedDict # photontorch import torch import photontorch as pt # other import numpy as np import matplotlib.pyplot as plt from tqdm.notebook import trange ``` -------------------------------- ### Run Photontorch Tests Source: https://github.com/flaport/photontorch/blob/master/README.md Execute tests for Photontorch from the root of the git repository using pytest. ```bash pytest tests ``` -------------------------------- ### Default Environment Simulation Source: https://github.com/flaport/photontorch/blob/master/examples/01_all_pass_filter.ipynb Runs a simulation using the default environment after exiting a context manager. This demonstrates the state of the environment outside the `with` block. ```python print("This was detected outside the context manager, " "with the default environment:") detected = nw(source=1) nw.plot(detected) plt.show() ``` -------------------------------- ### Print Circuit Parameters Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb Iterate through and print the optimizable parameters of a circuit, similar to how it's done in PyTorch. ```python for p in circuit.parameters(): print(p) ``` -------------------------------- ### Initial Circuit Plotting with Latency Adjustment Source: https://github.com/flaport/photontorch/blob/master/examples/09_XOR_task_with_MZI.ipynb Initializes the circuit and plots the detected signal against the target signal for validation data. It uses an interactive widget to adjust the latency and visualize its effect on the detected signal, helping to find an optimal latency value. ```python nw = Circuit() with pt.Environment(t=t): detected = nw(source=vastream.rename("t", "b"))[:,0,0,:] # lower dimensional sources should have named dimensions mse = pt.MSELoss(latency=0.0, warmup=0.0, bitrate=Rb, samplerate=Rs) @interact(latency=(0,3,0.1)) def _(latency=1.0): mse.plot(vastream, label="input") mse.plot(vatarget, label="target") mse.plot(detected, latency=latency, label="detected") plt.legend() plt.xlim(0,1) plt.show() ``` -------------------------------- ### Simulate and Plot Optimized Filter Source: https://github.com/flaport/photontorch/blob/master/examples/04_crow_optimization.ipynb Simulates the device with the current parameters and plots the detected output along with a marker for the target wavelength. ```python detected = allpass(source=1) allpass.plot(detected) plt.plot([1550,1550],[0,1]) plt.ylim(0,1) plt.show() ``` -------------------------------- ### Create Add-Drop Filter Network with Grating Couplers Source: https://github.com/flaport/photontorch/blob/master/examples/02_add_drop_filter.ipynb Builds an add-drop filter network incorporating grating couplers. This network includes sources, detectors, directional couplers, waveguides, and grating couplers, with defined links between them. ```python with pt.Network() as nw: # components nw.src = pt.Source() nw.through = nw.add = nw.drop = pt.Detector() nw.dc1 = nw.dc2 = pt.DirectionalCoupler(1 - transmission) nw.wg1 = nw.wg2 = pt.Waveguide(0.5 * ring_length, loss=0, neff=2.86) nw.wg_in = nw.wg_through = nw.wg_add = nw.wg_drop = pt.Waveguide( length=wg_length, loss=0.0, neff=2.86, trainable=True ) nw.gc_in = nw.gc_through = nw.gc_add = nw.gc_drop = pt.GratingCoupler( R=reflection, R_in=0, Tmax=peak_transmission, bandwidth=bandwidth, wl0=center_wavelength, ) # links nw.link('src:0', '0:gc_in:1', '0:wg_in:1', '0:dc1:2', '0:wg2:1', '1:dc2:3', '1:wg_drop:0', '1:gc_drop:0', '0:drop') nw.link('through:0', '0:gc_through:1', '0:wg_through:1', '1:dc1:3', '0:wg1:1', '0:dc2:2', '1:wg_add:0', '1:gc_add:0', '0:add') ``` -------------------------------- ### Import necessary libraries Source: https://github.com/flaport/photontorch/blob/master/examples/00_introduction_to_photontorch.ipynb Imports the required libraries for Photontorch, including torch, numpy, and matplotlib. ```python %matplotlib inline import torch import numpy as np import matplotlib.pyplot as plt import photontorch as pt ``` -------------------------------- ### Simulate Simple Add-Drop Filter in Frequency Domain Source: https://github.com/flaport/photontorch/blob/master/examples/02_add_drop_filter.ipynb Performs a frequency-domain simulation of the simple add-drop filter. The simulation sweeps across a range of wavelengths. Results are plotted. ```python with pt.Environment(wl=wavelengths, freqdomain=True): detected = nw(source=1) nw.plot(detected) ``` -------------------------------- ### Gradient-Based Optimization Source: https://context7.com/flaport/photontorch/llms.txt Optimizes photonic circuit parameters using PyTorch optimizers for inverse design. Requires gradient computation enabled in the environment. ```python import photontorch as pt import torch circuit = Circuit(length=1.2e-5, neff=2.84, ng=3.2, loss=3e4) # Define training environment with gradient tracking train_env = pt.Environment( wl=1525e-9, # Target wavelength for optimization freqdomain=True, grad=True # Enable gradient computation ) # Define target (zero transmission at resonance) target = 0 # Use PyTorch Adam optimizer optimizer = torch.optim.Adam(circuit.parameters(), lr=0.1) # Training loop with train_env: for epoch in range(100): optimizer.zero_grad() detected = circuit(source=1) loss = ((detected - target) ** 2).mean() loss.backward() optimizer.step() if epoch % 20 == 0: print(f"Epoch {epoch}, Loss: {loss.item():.6f}") # Print optimized parameters for p in circuit.parameters(): print(p) ``` -------------------------------- ### Frequency Domain Simulation Source: https://context7.com/flaport/photontorch/llms.txt Performs a wavelength sweep to analyze the spectral response of a photonic circuit. Requires matplotlib for plotting. ```python import photontorch as pt import numpy as np import matplotlib.pyplot as plt # Define circuit (from earlier) circuit = Circuit(length=1.2e-5, neff=2.84, ng=3.2, loss=3e4) # Create frequency domain environment freq_env = pt.Environment( wl=1e-6 * np.linspace(1.45, 1.65, 1000), freqdomain=True ) with freq_env: # Simulate with constant source amplitude detected = circuit(source=1) # Plot transmission spectrum circuit.plot(detected) plt.xlabel('Wavelength (m)') plt.ylabel('Power') plt.title('Frequency Response') plt.show() ```