看到很多人在论坛里问到UDS的问题,都没有人回答和帮助啊~跟站长
@ZEMAX中文论坛站长 聊了一下,想自己写个帖子出来,跟大家一起分享和讨论。第一次写帖子,态度还是很端正的,毕竟每个字都是自己type的。
想必还是有很多人会用到或想用ZEMAX的自定义表面功能吧,毕竟ZEMAX自带的表面不是都满足我们的要求。因为里面很多参数的comment都没有,计算的是什么都不知道(个人觉得ZEMAX写模板的那群人就是不想让大家知道的),所以对于想要自己建立一个表面的同志,开始总是很难的(PS: 至少自己是这样,哈哈~)。
在这里专门建一个关于探讨自定义表面问题的帖子,希望各路同仁和大牛多多探讨,帮助大家可以弄明白这里面的猫腻啊。
//////////分界线来一个,下面主要以
衍射光栅 为例////////////
先把ZEMAX手册里关于UDS的内容熟悉一下:
定义一个 UDS DLL 需要两个文件:一个诸如 MY_SURF.C 的 C(或 C++)原代码文件,一个名为USERSURF.H 的head文件。我们只要对 C 文件里的code按照需求进行修改。 找到DLL surfaces路径(C:\Program Files\Zemax OpticStudio\DLL\Surfaces)下的文件夹,其中会看到很多C和DLL 文件,还有一个head文件。
打开usersurf.h会看到里面都是结构体,其中定义了很多参数(这里面定义的每个参数都有注释,还是很明确的)。这些参数会传递到C文件中计算并回传给ZEMAX。在名为“FIXED_DATA”的结构体中有一个type参数,这个type将控制C中计算的参数类型,是由“Switch-case”的函数实现的。 type的值从 0-10 ,分别指:
8-10在grating里是没有的。
OK,那我们进入到code里面......
前面的DLL Main是DLL程序的入口函数,还有一个Refract是衍射函数的申明,不管它们,直接看主函数就好了。
主函数(nt __declspec(dllexport) APIENTRY UserDefinedSurface(USER_DATA *UD, FIXED_DATA *FD)),其中,USER_DATA、FIXED_DATA就是从head文件传过来的指针了,主函数里数据的变化会马上改变它们的值。
主函数中定义了很多接下来会用到的变量,int和double类型的,这么一堆变量都没有一个说明的~~在计算中所有要用到的变量都在这里定义的,这里的变量和参数栏中的参数不一样,参数栏提供的功能是在ZEMAX计算过程中用户可进行修改的参数,比如光栅周期、衍射级次等。
这里
分两种情况来讨论比较轻松一点:情况一是自定义的表面为平面;情况二是自定义的表面为曲面。
情况一:当表面为平面时,这就简单多了,因为不用计算sag,所以可以跳过很多步。
case 0:case里面还有switch函数,是由FD->numb控制的。case 0,给该表面起个名字;case 1,是否旋转对称;case 2,是否折变介质。
case 1:定义参数栏名称,这里总共可以定义8个,已经有两个了,光栅周期(“Lines/|ìm”)和衍射级次(“order”)。如果还有更多的参数,在后面加case就行了。
case 2:定义附加参数栏名字,最多可以定义242个附加参数。没有就不用管它~~
case 3:计算sag。如果是平面则忽略此步(在情况二中分析里面的计算)。
case 4、6、7:don't care。
case 5:最关键的部分,需要paste上代码来解释一下。
这一块if语句用于计算表面法线,意思就是 判断表面是否为平面,若为平面则表面法线为{0,0,-1},否则根据曲率和光线的方向余弦计算对应的表面法线。这块看不懂其实还是可以不管它~~
这一块就是我们要计算的啦,计算相位和相位的变化~~终于到了最关键的时刻。
首先把参数传过来,包括光栅周期T、衍射级次M、波长M,以及自己之前定义的一系列参数bra bra~~
然后,计算相位方程和相位的偏微分。path是由相位方程给出的,dpdx和dpdy是path在x和y方向的偏微分。这里要用到光栅方程n'sinθ'-nsinθ=MTL。
(注意:code中的path对2π/λ进行了归一化处理)
这里段是利用上面得到的相位微分,计算新的光线方向余弦。ZEMAX为了获得光线的偏移,修改光程长度来包含相位的变化。这是ZEMAX中衍射组件的“折射定义”。
完事了~~所以,光栅DLL 我们要做的就是在这部分制造出我们的光栅面型,它与光栅周期、光栅线分布等参数有关,再得到这一面型的相位方程就OK了。
情况二:当表面不是平面时就复杂一些,因为要计算表面矢高sag。其实也不难,最关键的还是case 5定义光栅。
这里我给出case 3的code的备注,相关公式在手册上可以查到,需要自己推导一下。
表面矢高的计算是要根据曲面的定义的方程而改变的,不一样的曲面得到的不同。
对于曲面,还涉及case 4的计算,这里计算近轴光线追迹。
图中有我的comment,大概描述了一下,想知道原理可以参考公式自己推导一下。不知道也没关系~
接下来,要解决一个很重要的问题,这是在ZEMAX的所有UDS里都使用到的,就是Snell折射定律计算光线的路径:
Code中建立了一个专门计算光线折射的函数Refract,在Zemax计算近轴光线追迹和真实光线追迹的时候都会调用它。而代码中折射的计算是基于矢量的,一般不容易明白,但是折射定律是Zemax光线变化的核心内涵。这部分代码如下:
把当前的前后表面折射率、方向余弦和表面法线以实参的形式传递进来。
首先,建立坐标系,公式的推导如下:
用单位矢量表示入射光线、出射光线、表面法线和切平面方向。折射矢量可从法线方向与切线方向的矢量之和得出:
同理,入射矢量可根据矢量关系得:
将切线m解出得:
根据Snell定律:
且余弦为:
把(2)、(3)、(4) 代入 (1),简化得:
最终,将矢量分解到X、Y、Z坐标上就得到code中的表达式。花括号中的式子就是code中的变化量gamma。此外,当根号内的值为负数时,代表全反射,返回值为-1,将把当前的-surf返回给Zemax表示折射。
////////////结束的分界线///////////////////////////////
OK,写了一上午,不容易啊。
个人版权,请勿随意粘贴,供大家在此探讨的。
期待坛子中的大牛可以指导一下,个人的理解,不知道里面有没有错误。有其他表面定义的见解也可以分享出来,这是一个关于UDS的帖子。
欢迎指正和讨论!!!!!!!!!!!!!!