In this article, a simulation method with an example of optimization and tolerance analysis for an exit pupil expander (EPE) system using a 2D grating as outcoupler is proposed and demonstrated.
In this workflow, we use Lumerical to construct the grating model and simulate its response with the RCWA solver. The full EPE system is built in OpticStudio and dynamically link to Lumerical for integrating accurate grating model. The outcoupler (OC) is a 2D grating with a complex structure which features are optimized locally. Finally, optiSLang is used to overall control the system level optimization by modifying the grating model to achieve the required optical performance in the whole EPE system.
Overview
Understand the simulation workflow and key results
The design of an AR system with an EPE that allows to increase the size of the eye box is a challenge for the optimization at the system level because it presents a lot of parameters. One solution is to use several 1D gratings to replicate the pupil, see Optimization of an Exit Pupil Expander with 1D gratings for more details. In this article, the waveguide is composed of two gratings designed in Lumerical. The incoupler (IC) is a 1D slant grating, and the outcoupler (OC) is a 2D grating composed of parallelogram pillars. These gratings are used in the OpticStudio optical system via a Dynamic Link (See Dynamic workflow between Lumerical RCWA and Zemax OpticStudio ). The 2D OC grating is divided into several tiles where the grating parameters are tuned separately.
The optimization is then handled by optiSLang via a Python node. The use of optiSLang provides great advantages such as the capability to perform preprocessing and postprocessing during each optimization cycle (e.g. convolution of the result with a pupil function). In addition, instead of using directly all the individual grating characteristics in the different zones, the parameters can be controlled by defining a function in the python code, reducing the total number of variables, and therefore the optimization time. The process is initiated by a Sensitivity block so that the system can identify the most impactful parameters when running the optimization. In the article Optimization of an Exit Pupil Expander with 1D gratings , one can learn how to optimize the most basic characteristics of 1D gratings: height, duty cycle, and slant angle. In the article Exit Pupil Expander with 1D2D Gratings , the design of a 2D grating in OpticStudio is presented, but the optimization is limited as it is performed only within OpticStudio. In this work, we demonstrate how optiSlang can be used to perform a complex optimization of a 2D grating by using 7 different variables to control locally the shape of parallelogram pillars.
This article is divided in 4 main steps as follows:
Step 1: Setting up the Optical system with Lumerical
In this section we present the optical system that is going to be optimized. It is the same type of system that we can be found in the article Exit Pupil Expander with 1D2D Gratings – Ansys Optics . Note that in the initialdesign, the energy is not spread throughout the full Eye box as most of the light is outcoupled after a few interactions with the fold grating and the outcoupler.
Step 2: Setting up the Optimization in optiSLang
The purpose of this article is to demonstrate how to use optiSlang to control the optimization of the optical system built with Zemax. This section introduces the parameters that are going to be used for the optimization, as well as the metrics used as optimization target.
Step 3: Check the optimization results
The optimization was already set, and results are available. In this section, we provide information on the structure of the optiSlang file, and explain how to visualize the results that came from the multiple runs of optimization.
Step 4: Update the system with the desired design
This final section is a step by step guide to select a specific design from the different runs and to push the corresponding parameters to the optical system.
Run and Results
Instructions for running the model and discussion of key results
Step 1: Setting up the Optical system with Zemax and Lumerical
 Open the file [[EPE_2D_outcoupler.zprj]] in Zemax OpticStudio to check the system settings.
The IC is a slant grating that is considered to already be optimized. The core of this system is the OC that is a 2D grating composed of parallelogram pillars arranged in a hexagonal periodic structure.
In the waveguide system built in OpticStudio, a collimated beam is incident on the IC grating, and propagates to the OC through the waveguide. The hexagonal periodic structure of the 2D grating allows the beam to propagate and distribute to a large region in the waveguide, as shown in the picture below. In this way, light propagates through the OC and is extracted toward the eye box at multiple locations, effectively replicating the pupil.
The detector is set to capture the rays directly at the output of the OC grating. The goal of the optimization is to enhance the uniformity of the irradiance map output toward the eye, while maximizing the total power.
To prepare for the optimization, the OC grating is divided into several zones within which the grating properties are going to be optimized independently.
Step 2: Setting up the Optimization in optiSLang
 Open the file [[EPE_2D_outcoupler.opf]] in optiSLang to check the optimization settings.
 Double click on the Python icon “EPE_2D_for_OptiSlang.py” to visualize the code.
This optimization is not going to be used to tune only the most basic parameters such as height and duty cycle. The 2D grating presents 7 parameters that are going to be used as variable, so that the shape of the pillars themselves can be optimized, as illustrated below.
For the optimization, the OC grating is divided into several zones within which the grating properties are going to be optimized independently. Instead of setting all these parameters individually in each area, the grating parameters across the multiples zones of the OC are controlled with a parametric function defined as follows:
where \(\nu\) stands for any of the variables \(d_C, d_R, d_L,\theta_C, \theta_R, \theta_L, h \), and \(n\) is \(1,2,3,4\), which corresponds to the tiles at the 4 corners. With this equation, the 7 grating parameters at each tile can be controlled by the parameters at the 4 corners with some weighting \(w_n\) and nonlinear power \(p\). Note that symmetry is also exploited to reduce the size of the systems and the number of variables.
In the attached folder, a python file EPE_2D_for_OptiSlang.py is prepared for linking optiSLang to OpticStudio. For more details on how to set up such a file, see the appendix of the article Optimization of an Exit Pupil Expander with 1D gratings – Ansys Optics .
The grating parameters are varied by optiSlang following a predefined optimization algorithm (e.g. Evolutionary Algorithm). The varied parameter values are set into the python code and flow it down to each grating tile in OpticStudio. In this process, the Python code plays a role to do the work converting these variables into the exact parameters in OpticStudio. This predataprocessing with a function defined in Python is only possible when we optimize the system with optiSLang instead of the builtin optimizer in OpticStudio. In this way, optiSLang can optimize the system based on some virtual or highlevel variables that are not directly exposed in the OpticStudio UI.
Once the parameters are set up, the remaining of the code consists of calling OpticStudio to trace rays and collect results from the detector. The other benefit of using optiSLang to optimize the system is postdataprocessing. In this optimization process, we don’t directly optimize the irradiance distribution on the eye box. Instead, we first do a convolution on the irradiance distribution with a pupil function, and then set the optimization target based on this convolved result. For this example, the optimization target are the contrast, total power, and uniformity as defined below:
$$ Constrast = \frac{MaxMin}{Max+Min} $$
$$ TotalPower = \frac{Power\_Received\_By\_Eye\_Box}{Power\_Incident\_On\_IC  Coupling\_Grating} $$
$$ Uniformity = \frac{Standard\_Deviation}{Total\_Power} $$
The final part of the Python code is to draw the result of the irradiance at the eye box, as well as its convolved result, and then export pictures. This is useful for users to check how the irradiance looks like for each of the optimized system directly within optiSLang postprocessing.
Step 3: Check the optimization results
 Double click on the Postprocessing (1) icon to visualize the results of the Optimization.
When the optimization starts, a sensitivity analysis is first performed to identify the most important parameters. With this input, the Evolutionary algorithm runs and produces a series of results. These results can be visualized directly in optiSLang in a Pareto plot.
The red marked designs in the following plot are called Pareto front. A Pareto front illustrates the trade off between multiple objectives, where no design dominates the other one regarding performance. That means all of these designs show up different balances of multiple criteria (e.g. Uniformity vs Total Power). We have picked up 3 results and show them below. For each design point corresponds a pair of plots showing respectively the contrast and the uniformity within the Eye Box.
Step 4: Update the system with the desired design

Copy/Paste the Sensitivity block into the page and double click on the block title “AMOP (1)” to edit it.
 In the “Adaptation” tab, check the “Show advanced settings” option and check "Use start design only".
 In the “Other” tab, Check the “Solve start designs again” option in the “Evaluation settings” menu.
 In the “Start Designs” tab, choose the option “import start values from system” and select the desired design identified on the Pareto Plot (e.g. #986).
 In OpticsStudio, click on the ‘Interactive extension’ button in the Programming tab, and then run the OptiSlang Simulation.
The optimization has already been done in the attached file and the optimized results can be visualized when opening the file. Sometime we might want to pick up an optimized design and investigate in OpticStudio. However, optiSLang only saves the input parameters in a table. We don’t keep the OpticStudio system. In order to select a specific design in optiSLang and push the parameters into the optical system in OpticStudio, we can duplicate the Sensitivity block and define its starting point to be the desired design. By disabling the dynamic sampling, running this block will simply read the parameter values from the selected design and push the corresponding data into OpticStudio. The user can then manually save the new system under another name. Another option to get the OpticStudio system with any picked design in optiSLang is to add a command in the python code to save the system as a .zmx file directly when running the optimization in optiSLang (e.g. TheSystem.SaveAs(‘design_optimized.zmx). Note the second method only works when we make the change in the Python before running the optimization in optiSLang.
Important model settings
Description of important objects and settings used in this model
 Since the system relies on a Python code, it is assumed that Python is installed as well as all the additional modules used called in the script.
 Ensure the correct version of Dynamic link is selected for all the grating surfaces.
 It is important to ensure the “Interactive Extension” is active in OpticStudio (Programming tab) before running anything in optiSLang.
 In this article we demonstrate that optiSlang can be used to handle a complex optimization problem with many parameters, but it is important to note that relying on the symmetry of the system when possible is always the best way to simplify the optimization.
Updating the Model with Your Parameters
Instructions for updating the model based on your device parameters
 The optical system in this example is presenting an EPE with two 1D gratings divided into several zones. It is up to users to customize the shape, nature, and position of the gratings. The shape and number of the tiles may also be customized directly in the optical system.
 The variables and optimization targets are defined when setting up optiSLang and can be customized. See the appendix of the article Optimization of an Exit Pupil Expander with 1D gratings for more details on how to set up the optimization model in optiSLang.
 In this article, the variables are defined indirectly with a function. In the Python code of the example, it is under the name ‘linsp’. Any custom function may also be used by the user, the definition can simply be updated in the Python code.
Taking the Model Further
There are some considerations that are not covered in this demonstration but users could pay more attention when they try to follow this process for their systems.
 In this demonstration, we only consider the central field, which is a collimated beam normally incident on the waveguide. For a more comprehensive optimization, more fields can be added to cover the uniformity in full field of view.
 Similarly, the system is only designed for a single wavelength. Depending on the system design, the optimization can include multiple wavelengths.
 Some irradiance distributions look more uniform but result in higher contrast. The criteria could be improved by modifying the Python code.
 An additional dimension to be optimized is the lattice angle. In the system presented, the pillars are arranged in a hexagonal structure, but Lumerical supports different arrangements that could bring further possibilities.
Additional Resources
Related Publications
 HanHsiang (Michael) Cheng, Yuan Chen, Alexandra Christophe, Sabrina Niemeyer, ChihHao Chen, Jens Niegemann, Milad Mahpeykar, Yihua Hsiao, YiHao Chen, Dylan McGuire, and Adam Reid "Optimization and tolerance for an exit pupil expander with 2D grating as outcoupler", Proc. SPIE 12449, Optical Architectures for Displays and Sensing in Augmented, Virtual, and Mixed Reality (AR, VR, MR) IV, 124490X (16 March 2023); https://doi.org/10.1117/12.2645565
See Also
 Optimization of an Exit Pupil Expander with 1D gratings
 Exit Pupil Expander with 1D2D Gratings
 Augmented Reality Optical System
Related Ansys Course