简介
本文提出并演示了一种以二维光栅耦出的光瞳扩展(EPE)系统优化和公差分析的仿真方法。
在这个工作流程中,我们将使用3个软件进行不同的工作 ,以实现优化系统的大目标。首先,我们使用Lumerical构建光栅模型并使用RCWA进行仿真。其次,我们在OpticStudio中构建完整的出瞳扩展系统,并动态链接到Lumerical以集成精确的光栅模型。最后,optiSLang用于通过修改光栅模型来全面控制系统级优化,以实现整个出瞳扩展系统所需的光学性能。
作者:Michael Cheng 翻译:陈媛
附件下载
概述
我们将首先在Lumerical和OpticStudio中构建仿真系统,它们是动态链接的(参见Dynamic workflow between Lumerical RCWA and Zemax OpticStudio)。 然后,OpticStudio 通过 Python 节点链接到 optiSLang 进行优化,如图 1 所示。
图 1 Lumerical通过动态链接到OpticStudio。OpticStudio 通过 Python 节点链接到 optiSLang。优化由optiSLang控制。
如图2所示,EPE系统包括两个用于耦入和耦出的光栅。 耦出光栅分为几个区,如左侧所示。 每个区都将经过优化,以具有不同的光栅形状。右图显示了光在 k 空间中的传播的变化情况。有关 k 空间的更多信息,请参阅以下文章:How to simulate exit pupil expander (EPE) with diffractive optics for augmented reality (AR) system in OpticStudio: part 1
图 2 光栅布局图以及光线在K空间的传播
第 1 步: 系统设置 (Lumerical)
打开附件中的ZAR文件时,两个光栅文件会被提取到设置的路径中。第一个光栅如图 3所示,它是耦入光栅中使用的二元光栅。该光栅是固定的,在优化过程中不会改变。
图 3 耦入光栅结构为二元光栅。
第二个 .fsp 文件如图 4 所示,它是一个具有 7 个变量的四边形柱体。在优化期间,耦出中的每个区都将使用不同的变量组合集进行优化 。有关优化设置的更多信息将在优化设置部分中进行说明。
图 4 耦出光栅中的结构为平行四边形支柱。
这两个.fsp文件都是用动态链接的形式在OpticStudio中用于模拟完整的EPE系统。有关动态链接的更多信息,请参阅 Dynamic workflow between Lumerical RCWA and Zemax OpticStudio.
第 2 步: 系统设置(OpticStudio)
如图5所示,在该系统中,准直光束入射到耦入光栅上,通过波导传播,并与第二个光栅耦合。 眼盒位于第二个光栅的较远部分。优化的目标是优化眼盒接收的均匀性和总功率。
图 5 初始EPE系统和眼盒辐照度。
在附件中有一个OpticStudio中建立的整个EPE系统的zar文件。如图 6所示,仅构建了第二个光栅一半的区域。这是因为系统具有对称性。从图 7 可以看出,探测器的参数镜像设置为 1,这意味着在光线追迹期间,将始终对-x和+x部分进行镜像。 这样一来,我们可以只用一半的光线获得相同的模拟结果。
图 6 OpticStudio中的 EPE 系统设置。
图7 探测器的镜像参数设置为 1,这意味着该探测器在 x 方向上镜像。
可以看出, 系统中的所有光栅物体都已使用动态链接DLL进行设置,如图 8所示。
图 8 为 EPE 系统中的光栅加载动态链接 DLL。
第3步: 优化设置(optiSLang)
3-1. Python 用于评估系统
附件中包含了一个python文件EPE_2D_for_optiSLang.py,用于将optiSLang链接到OpticStudio。 使用python代码将 Ansys optiSLang附带的优化器与求解器Ansys Zemax OpticStudio + Ansys Lumerical链接非常有用。优势在于可以在每个优化周期中进行数据的预处理跟后处理,灵活性非常高。本章节会对代码结构进行解释。
代码的基本结构首先由 OpticStudio 中的按钮生成,如图 9 所示。 有关编写API以访问OpticStudio的更多信息,请参阅知识库文章:Knowledgebase > Programming > API
图 9 生成 Python 交互式扩展代码的样板。
另外几个模块被导入到样板中。 模块numpy,scipy用于对来自眼盒的辐照度数据进行后数据处理。模块 matplotlib 用于在眼盒上绘制和导出辐照度 以供以后查看。导入time和random模块,以便计时器跟踪计算时间。
通过尝试读取变量OSL_WORKING_DIR,我们可以知道这个 Python 代码是由 optiSLang 调用还是手动调用。当 optiSLang 调用 Python 代码时,将创建一些称为环境变量的变量来传递一些 optiSLang 信息。即使这些变量未在 Python 文件中定义,当 optiSLang 调用代码时,它们是可用的。 有关 optiSLang 中的 En vironment 变量的更多信息,请参阅 optiSLang 用户指南。
在这个Python 代码中,有 32 个变量,如 clen1、h2、rot4、w1 和 power,用于优化,需要由 optiSLang 定义。 我们会将这些变量设置为 optiSLang中的参数,在灵敏度分析或优化时,optiSLang将自动改变它们的值。 如果我们不是从optiSLang直接运行这个Python代码,那么这些变量的值将是常量,如下面的代码所示。
如图10所示,每个区的光栅参数是通过预设的4个角的数据通过插值来确定的。 其中 ν 是 dC、dR、dL、θ C、θ R、θ L 、 h , n 是 1,2,3,4,对应于 4 个角。通过这个公式,每个区上的7个光栅参数可以通过具有一定权重(wn)和非线性值(p)的4个角的参数来控制。
图 10 从 4 个角插值的各个区的参数计算。
optiSLang 按照预定义的优化算法改变这些参数。不同的参数值被设置到python代码中,这将进一步设置OpticStudio中每个光栅块的参数。 在这个过程中,Python 代码扮演着将这些变量转换为 OpticStudio 中精确参数的工作。只有当我们使用 optiSLang 而不是 OpticStudio 中的内置优化器优化系统时,这种预数据处理才有可能。 通过这种方式,optiSLang可以根据一些未直接暴露在OpticStudio UI中的虚拟或高级变量来优化系统。
设置参数后,我们使用以下代码段追迹光线。
使用 optiSLang 优化系统的另一个好处是数据后处理。 在这个优化过程中,我们不会直接优化眼盒上的辐照度分布。我们首先使用瞳孔函数对辐照度分布进行卷积,如图 11 所示,然后将优化目标设置为该卷积结果的均匀性。 这个结果的x和y轴可以解释为人眼在眼盒中的偏移。z轴是人眼看到的平均辐照度。
图 11 使用瞳孔函数对辐照度分布进行卷积。
根据卷积结果,我们可以计算对比度 、总功率和均匀性,如下所示。
这些标准的代码定义如下。 在这种情况下,我们主要希望针对 Contrast 和 Total Power 进行优化。均匀性的功能类似于对比度,两者都希望眼盒上的辐照度均匀。 尽管它们用于相同的目标,但它们使用不同的定义,在这里我们考虑两者。
Python代码的最后一部分,如下所示,绘制了眼盒辐照度的结果及其卷积结果。然后导出图片。这对于用户直接在optiSLang后处理中检查每个优化系统的辐照度分布非常有用。
3-2. 参数系统
准备好 Python 代码后,我们就可以开始在 optiSLang 中进行优化了。 第一步是在 optiSLang中打开一个空文件,拖动求解器向导,放入scenery中,然后选择Python集成。
如下所示,会弹出向导窗口 ,显示Python代码。 我们将首先通过右键单击变量(如 clen1)来设置参数,然后选择用作参数。 我们将对从 clen1 到 power 的所有变量执行此操作。如下所示,所选变量将显示为左列“参数”。
设置完参数后,我们应该测试 Python 代码是否可以成功运行。为此,我们应该打开OpticStudio并打开交互式扩展模式,如下所示。然后在求解器向导中,我们可以单击向下箭头并选择“Test run with inputs”,如下所示。 如果它运行良好,您应该看到,在OpticStudio窗口中,交互式扩展的对话框将显示为“已连接”。
如果测试运行失败,其中一个可能的原因是 Python 环境不对。用户可以更改设置,如下所示,以查看是否可以解决问题。
计算完成后(在我们的测试中大概需要 13 分钟),我们应该在日志中看到消息“Manual test run successfully processed”,如下所示。现在,如果我们转到***.opd文件夹(可以通过右键单击系统头并选择“show working directory”轻松访问),我们可以找到辐照分布被导出到文件夹“\Parametric_solver_system\design_data”中,这是Python代码中指定的路径。
类似于对参数的设置,我们可以对结果做相同的操作。 在这里,我们将右键单击 Python 代码中的变量““Uniformity”, “Contrast”, 和 “TotalPower”然后选择“Use as response”。然后,这 3 个变量将在Responses的右侧列中显示。
向导的下一页要求用户定义每个参数的参考值和范围。 参考值将只遵循我们在上一步中设置参数时的定义。范围由设计师决定,没有标准参考值。用户可以在下载链接中查看随附的optiSLang文件,作为在优化过程中确定范围的参考。 请注意,此范围是绝对的。在优化过程中,参数不会突破边界。这与Zemax OpticStudio优化的设置不同。
在向导的下一页中,我们需要根据给定的响应设置条件。如下图所示,我们可以将响应拖到底部以设置约束或目标。在这种情况下,我们设置了 3 个目标,以最小化对比度、均匀性以及最大化总功率。我们还可以为对比度和总功率设置 2 个约束来告诉 optiSLang,避免一些极端情况,即结果是均匀的,而总功率极低,或者相反的情况。
最后一页不需要操作。单击“完成”按钮后,工作区中将显示参数系统。
3-3. (可选)设置并行计算
本节中的操作不是必须的。 在这里,我们将展示如何在optiSLang端设置并行计算以加快优化速度。 如果用户拥有多个 Lumerical FDTD 求解器许可证,则可以考虑这样做。 要进行此设置,第一步是右键单击参数化系统块,选择“编辑”,然后将极限最大值并行设置为6或任何不大于 8的数字或Lumerical FDTD求解器许可证的总数量,如下所示。
注意我们需要做同样的事情来右键单击 Python 节点并选择“编辑”。 要设置详细信息,我们需要首先单击右上角的汉堡标记,检查属性和占位符,然后单击“确定”按钮。 然后我们可以将最大并行设置为 6,如下所示。 请注意,我们还需要在窗口的下部将最大值并行设置为 6。 如果先设置此参数,上面的 MaxParallel 也会自动更改,但仔细检查它是否按预期设置更安全。
最后,建议检查“Retry execution”,将重试次数设置为 20,并将尝试间隔延迟设置为 1000 毫秒。 此设置可避免 optiSLang 尝试访问具有 1 个以上线程的同一 OpticStudio 实例的争用条件。
如果并行设置是多个,在运行optiSLang时,我们还需要打开相同数量的OpticStudio实例,那么optiSLang可以为每个实例创建一个线程。
3-4. 灵敏度以及优化设置
下一步是设置灵敏度分析。一般来说,灵敏度分析是一种找出对响应影响最大的最重要参数的方法,并生成显示响应和参数变化之间关系的最佳元模型,以更好地了解系统行为。
灵敏度系统可以通过将向导拖动到参数化系统块来设置,如下所示。参数和条件将被复制,我们不需要再次设置。 默认情况下,它将建议AMOP模型,我们可以保留此设置。 AMOP是一种迭代抽样方法,将设计采样到设计空间中,直到达到目标标准 - 最大设计或模型质量。因为本模型具有高度非线性,无法达到足够的模型质量,因此在下一阶段将进行实际运行优化。
类似地,我们将优化向导拖到 AMOP 模块中以进行优化。请注意,当它询问优化方法时,我们应该选择Real Run,因为该系统永远不会有高质量的最佳预后元模型(MOP)。 MOP是在(Most and Will 2008)中提出的,它基于对最佳输入变量集和最合适的近似模型(多项式或具有线性或二次基的MLS)的搜索。 对于优化算法,建议使用进化算法,它适用于非常不均匀和不连续的解空间。
3-5. 开始优化
用户只需打开一个OpticStudio并在交互式扩展模式下准备就绪即可。 注意必须取消选中断开连接时自动关闭,如下所示。 请注意,如果并行计算已设置为6,如上所述,用户将需要在此处打开相同数量的实例(例如6个),optiSLang将同时访问所有实例。
当一切准备就绪后,我们可以单击按钮进行优化。
在这个示例系统中,我们花了大约 2~3 天的时间在普通台式 PC 上运行此优化。
3-6. 优化结果
通过双击进化算法块扩展的后处理可以找到优化结果,如下所示。
下图中的红色标记设计称为帕累托边界。一般来说,帕累托边界显示了多个目标之间的权衡,即不存在一个设计在各项指标上均优于另一个的情况。这意味着所有这些设计都显示了多个标准的不同平衡。 我们选择了 3 个结果,如下所示 。 986号的对比度比946号高,同时看起来更均匀。这意味着这里使用的标准可以改进,以更好地匹配人类视觉。
后续
以下是本文未涵盖的一些注意事项,但用户在尝试为其系统遵循此过程时可能需要留意。
-在本演示中,我们只考虑中心视场,即通常入射在波导上的准直光束。为了更全面的优化,可以添加更多视场以覆盖全视野下的均匀性。
-实际上,该系统仅设计用于单个波长。 根据系统设计,优化可以包括多个波长。
-一些辐照度分布看起来更均匀,但对比度更高。可以通过修改 Python 代码来改进标准。
评论
请登录写评论。