├── .gitignore
├── README.md
├── SUMMARY.md
├── docs
├── .nojekyll
├── 3db功分.md
├── README.md
├── _coverpage.md
├── _images
│ ├── 2021-01-04-17-29-03.png
│ ├── 2021-01-06-15-58-39.png
│ ├── 2021-01-06-15-59-44.png
│ └── 2021-01-06-16-01-34.png
├── _media
│ └── icon.svg
├── _sidebar.md
├── index.html
├── 例程.md
├── 前言.md
├── 安装.md
├── 测试.md
└── 附录.md
└── src
├── gen_data
└── main.py
├── material.mdf
└── transpose
├── gen_data.py
└── initbase.py
/.gitignore:
--------------------------------------------------------------------------------
1 | /testdocs
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 文档地址
2 |
3 | https://photonic-ai-communication.github.io/lumerical-python-script/#/
4 |
5 |
6 | ## 说明
7 |
8 | 此文档为记录、备份lumerical fdtd/mode 的python api以及相关使用方法。
9 |
10 | 以供组内成员查阅、使用。
11 |
12 | 文档中所涉及到的所有源码均在src文件夹目录下
13 |
14 | material.mdf为材料文件
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # SUMMARY
2 |
3 | ### 前言
4 |
5 | * [前言](前言.md)
6 |
7 | ### 安装
8 | * [安装:前言](安装.md#init)
9 | * [lumerical](安装.md#lumerical)
10 | * [python](安装.md#python)
11 | * [python+lumerical](安装.md#python+lumerical)
12 | * [结语](安装.md#结尾)
13 |
14 | ### 例程
15 | * [例程:简单的例子](例程.md#ladder)
16 | * [发生了什么?](例程.md#what_happend)
17 |
18 | ### 附录
19 |
20 | * [关于python中的包管理](附录.md#pipinstall)
21 | * [更换下载源](附录.md#change_source)
22 | * [包安装方式](附录.md#install)
23 | * [关于函数、方法的查询](附录.md#how2find)
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Photonic-AI-Communication/lumerical-python-script/ba1b44ea665e7b0ec347970d67f1dd18bd2170f7/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/3db功分.md:
--------------------------------------------------------------------------------
1 | # 例程:功率分支器
2 |
3 | 在这个例子中,我们的设计目标是一个简单的片上功率分支器,光从一端输入,从另一端的两个端口输出。
4 |
5 | 要求损耗尽可能低,即3db功分器
6 |
7 | > 本节例程源码处于src/transpose目录下
8 |
9 | 这个例程主要含有以下功能:
10 |
11 | 1. 最简单的拓扑优化(爬山、dbs……管你怎么叫了……)
12 | 2. 多进程同时仿真
13 | 3. 模式分解器的使用
14 |
15 | ## 开始
16 |
17 | 未完待续……
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # 文档地址
2 |
3 | https://photonic-ai-communication.github.io/lumerical-python-script/#/
4 |
5 |
6 | ## 说明
7 |
8 | 此文档为记录、备份lumerical fdtd/mode 的python api以及相关使用方法。
9 |
10 | 以供组内成员查阅、使用。
11 |
--------------------------------------------------------------------------------
/docs/_coverpage.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 
4 |
5 | # lumerical+python=efficiency 3.5
6 |
7 | > 用python操作lumerical的api进行各种仿真
8 |
9 |
10 | [GitHub](https://github.com/Photonic-AI-Communication/lumerical-python-script/)
11 | [Get Started](#前言)
--------------------------------------------------------------------------------
/docs/_images/2021-01-04-17-29-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Photonic-AI-Communication/lumerical-python-script/ba1b44ea665e7b0ec347970d67f1dd18bd2170f7/docs/_images/2021-01-04-17-29-03.png
--------------------------------------------------------------------------------
/docs/_images/2021-01-06-15-58-39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Photonic-AI-Communication/lumerical-python-script/ba1b44ea665e7b0ec347970d67f1dd18bd2170f7/docs/_images/2021-01-06-15-58-39.png
--------------------------------------------------------------------------------
/docs/_images/2021-01-06-15-59-44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Photonic-AI-Communication/lumerical-python-script/ba1b44ea665e7b0ec347970d67f1dd18bd2170f7/docs/_images/2021-01-06-15-59-44.png
--------------------------------------------------------------------------------
/docs/_images/2021-01-06-16-01-34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Photonic-AI-Communication/lumerical-python-script/ba1b44ea665e7b0ec347970d67f1dd18bd2170f7/docs/_images/2021-01-06-16-01-34.png
--------------------------------------------------------------------------------
/docs/_media/icon.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/docs/_sidebar.md:
--------------------------------------------------------------------------------
1 |
2 | * 快速开始
3 | * [前言](前言.md)
4 | * [安装](安装.md)
5 |
6 | * 例程
7 | * [简单的例子](例程.md)
8 | * [功率分支器](3db功分.md)
9 |
10 |
11 | * 附录
12 | * [附录](附录.md)
13 | * [特殊代码测试](测试.md)
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/docs/例程.md:
--------------------------------------------------------------------------------
1 | # 例程:简单的例子
2 |
3 | 我们先来看一个简单的仿真例子,这个例子中我们定义了一个简单的器件,并放置了光源,定义了仿真区域、边界条件、输入模式等等,并在最后将仿真的结果通过监视器输出,以numpy格式导入到了python中,并最后通过matplotlib可视化。
4 |
5 | **注意:本示例中引用了bidict、matplotlib等软件包,若没有安装,请参考附录中的[软件包安装](附录.md#pipinstall)**
6 |
7 | ```
8 | import lumapi
9 | import numpy as np
10 | from collections import OrderedDict
11 | from bidict import bidict
12 | import matplotlib.pyplot as plt
13 |
14 | def init_base(mode,size=(2,2)):
15 | mode.switchtolayout()
16 | # 基底生成
17 | # mode.importmaterialdb("fdtd_files/material.mdf") #加载材料数据
18 | mode.addrect(x=0, y=0.0, z=-1.11e-6,x_span=2e-5,y_span=1e-5,z_span=2e-6,name="box",material="SiO2 (Glass) - Palik")
19 | mode.addrect(x=0, y=0.0, z=0,x_span=2.6e-6,y_span=2.6e-6,z_span=0.22e-6,name="Si (Silicon) - Palik",material="Si (Silicon) - Palik")
20 | mode.addrect(x=-5.15e-6, y=0.0, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="in",
21 | material="Si (Silicon) - Palik")
22 | mode.addrect(x=5.15e-6, y=0.75e-6, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="out1",
23 | material="Si (Silicon) - Palik")
24 | mode.addrect(x=5.15e-6, y=-0.75e-6, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="out2",
25 | material="Si (Silicon) - Palik")
26 | mode.addmesh(x=0, y=0, z=0, x_span=2.6e-6, y_span=2.6e-6, z_span=0.22e-6, name="mesh",
27 | dx=0.02e-6,dy=0.02e-6,dz=0.02e-6,)
28 | mode.addvarfdtd(x=0, y=0, z=0,x_span=4e-6, y_span=4e-6, z_span=0.8e-6,simulation_time=1000e-15,x0=-1.48565e-6)
29 |
30 | #通过OrderedDict顺序设置模型参数
31 | source_props = OrderedDict([("name", "source"), ("injection axis", "x"),
32 | ("x", -1.7e-6), ("y", 0),("y span", 2e-6),
33 | ("selected mode number",2),
34 | ("center wavelength",1.55e-6),("wavelength span",0.2e-6),
35 | ("optimize for short pulse", 1)
36 | ])
37 | mode.addmodesource(properties=source_props)
38 |
39 | # OrderedDict也可以这样给
40 | mode.addpower(properties=OrderedDict([("name", "T1"), ("monitor type", "2D X-normal"),
41 | ("x", 1.45e-6), ("y", 0.75e-6),("z",0),
42 | ("y span", 0.5e-6),("z span",0.4e-6),
43 | ("override global monitor settings", True),("frequency points",1)]))
44 | mode.addpower(properties=OrderedDict([("name", "T2"), ("monitor type", "2D X-normal"),
45 | ("x", 1.45e-6), ("y", -0.75e-6),("z",0),
46 | ("y span", 0.5e-6),("z span",0.4e-6),
47 | ("override global monitor settings", True),("frequency points",1)]))
48 |
49 |
50 | # pattern生成
51 | rows, columns = size[0], size[1]
52 | mode.addstructuregroup(name="666")
53 | x_span = 2.6e-6 / columns
54 | y_span = 2.6e-6 / rows
55 | for row in range(rows):
56 | for column in range(columns):
57 | #模型在放置之后,默认选择的就是这个模型,就像下面这里,放置矩形之后可以直接将其加入到模型组之中,不用重新选择
58 | mode.addrect(x=-1.3e-6 + x_span / 2 + column * x_span, x_span=x_span,
59 | y=1.3e-6 - y_span / 2 - row * y_span, y_span=y_span,
60 | z=0, z_span=0.22e-6, name=str(row) + "r" + str(column) + "c",
61 | material="etch")
62 | mode.addtogroup("666")
63 |
64 | def change_pattern(mode,pattern_matrix):
65 | mode.switchtolayout()
66 | pattern_dic=bidict({
67 | "Si (Silicon) - Palik":1,
68 | "etch":0
69 | })
70 | for row in range(pattern_matrix.shape[0]):
71 | for column in range(pattern_matrix.shape[1]):
72 | mode.select("666::"+str(row)+"r"+str(column)+"c")
73 | pix = mode.getObjectBySelection()
74 | material_name=pix.material
75 | if pattern_dic[material_name]!=pattern_matrix[row][column]:
76 | pix.material=pattern_dic.inverse[pattern_matrix[row][column]]
77 |
78 | def get_result(mode):
79 | t1 = mode.getresult("T1", "E")["E"].squeeze()
80 | t2 = mode.getresult("T2", "E")["E"].squeeze()
81 | #这里a,b是两个监视器的电场幅值,即xyz方向的平方相加开根
82 | a = np.sqrt(np.sum(np.power(np.abs(t1), 2), axis=1))
83 | b = np.sqrt(np.sum(np.power(np.abs(t2), 2), axis=1))
84 | return a,b
85 |
86 | if __name__ == '__main__':
87 | row_num = 5
88 | column_num = 5
89 |
90 | mode = lumapi.MODE()
91 | init_base(mode, size=(row_num, column_num))
92 | #保存为项目文件
93 | mode.save("fdtd_files/base"+str(row_num)+"_"+str(column_num)+".lms")
94 |
95 | # 初始化pattern
96 | best_pattern_matrix = np.random.randint(0, 2, (row_num, column_num))
97 | change_pattern(mode,best_pattern_matrix)
98 | mode.run()
99 | a,b=get_result(mode)
100 |
101 | #绘图,可以和软件中自带的可视化比较一下
102 | fig, ax = plt.subplots(1)
103 | ax.plot(np.arange(len(a)),a,c='r',label='T1')
104 | ax.plot(np.arange(len(b)), b, c='b', label='T2')
105 | plt.legend()
106 | plt.show()
107 |
108 | ```
109 |
110 | 以上程序运行结束之后会画出两个输出端口的电场幅值分布:
111 |
112 | 
113 |
114 |
115 | 对应mode中的监视器可视化:
116 |
117 | 
118 |
119 | 器件结构:
120 |
121 | 
122 |
123 | 能够看到数据正确。
124 |
125 | *********
126 | ## 发生了什么?
127 | 如果程序运行顺利,我们应该能看到一个非常酷炫的效果,别慌。
128 |
129 | 接下来我们详细分析程序运行逻辑
130 |
131 | ```
132 | if __name__ == '__main__': #这里是程序的入口,运行的时候这里最先运行
133 | row_num = 5 #定义了我们器件的离散网格数量
134 | column_num = 5
135 |
136 | mode = lumapi.MODE() #通过lumapi,我们启动了一个mode仿真窗口,mode就代表了这个仿真的窗口对象,接下来的一系列操作都得通过mode这个对象进行
137 |
138 | init_base(mode, size=(row_num, column_num)) #我们将mode对象和我们定义的器件离散网格数量传入到了init_base这个函数当中,这个函数就开始生成我们器件的基本结构。
139 |
140 |
141 | #保存为项目文件
142 | mode.save("fdtd_files/base"+str(row_num)+"_"+str(column_num)+".lms")
143 |
144 | # 初始化pattern
145 | best_pattern_matrix = np.random.randint(0, 2, (row_num, column_num)) #通过numpy,我们生成了一个随机的二值化矩阵,矩阵大小同样为离散网格的数量
146 |
147 | change_pattern(mode,best_pattern_matrix) # change_pattern函数接收mode对象和我们随机的矩阵,将器件结构更改为随机矩阵对应的结构
148 |
149 | mode.run() #开始仿真
150 | a,b=get_result(mode) #仿真结束,get_result函数从mode对象中获取我们所需要的结果。
151 |
152 | #绘图,可以和软件中自带的可视化比较一下
153 | fig, ax = plt.subplots(1)
154 | ax.plot(np.arange(len(a)),a,c='r',label='T1')
155 | ax.plot(np.arange(len(b)), b, c='b', label='T2')
156 | plt.legend()
157 | plt.show()
158 |
159 | ```
160 |
161 | 经过main函数之后,我们打开了一个mode仿真窗口,初始化了器件结构,更改了结构,并进行了仿真,最后得到了仿真结果,并通过matplotlib可视化。
162 |
163 | 接下来对程序中进行各种处理的函数进行分析:
164 |
165 | ```
166 | def init_base(mode,size=(2,2)):
167 | mode.switchtolayout()
168 | # 基底生成
169 | # mode.importmaterialdb("fdtd_files/material.mdf") #加载材料数据
170 | mode.addrect(x=0, y=0.0, z=-1.11e-6,x_span=2e-5,y_span=1e-5,z_span=2e-6,name="box",material="SiO2 (Glass) - Palik")
171 | mode.addrect(x=0, y=0.0, z=0,x_span=2.6e-6,y_span=2.6e-6,z_span=0.22e-6,name="Si (Silicon) - Palik",material="Si (Silicon) - Palik")
172 | mode.addrect(x=-5.15e-6, y=0.0, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="in",
173 | material="Si (Silicon) - Palik")
174 | mode.addrect(x=5.15e-6, y=0.75e-6, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="out1",
175 | material="Si (Silicon) - Palik")
176 | mode.addrect(x=5.15e-6, y=-0.75e-6, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="out2",
177 | material="Si (Silicon) - Palik")
178 | mode.addmesh(x=0, y=0, z=0, x_span=2.6e-6, y_span=2.6e-6, z_span=0.22e-6, name="mesh",
179 | dx=0.02e-6,dy=0.02e-6,dz=0.02e-6,)
180 | mode.addvarfdtd(x=0, y=0, z=0,x_span=4e-6, y_span=4e-6, z_span=0.8e-6,simulation_time=1000e-15,x0=-1.48565e-6)
181 |
182 | #通过OrderedDict顺序设置模型参数
183 | source_props = OrderedDict([("name", "source"), ("injection axis", "x"),
184 | ("x", -1.7e-6), ("y", 0),("y span", 2e-6),
185 | ("selected mode number",2),
186 | ("center wavelength",1.55e-6),("wavelength span",0.2e-6),
187 | ("optimize for short pulse", 1)
188 | ])
189 | mode.addmodesource(properties=source_props)
190 |
191 | # OrderedDict也可以这样给
192 | mode.addpower(properties=OrderedDict([("name", "T1"), ("monitor type", "2D X-normal"),
193 | ("x", 1.45e-6), ("y", 0.75e-6),("z",0),
194 | ("y span", 0.5e-6),("z span",0.4e-6),
195 | ("override global monitor settings", True),("frequency points",1)]))
196 | mode.addpower(properties=OrderedDict([("name", "T2"), ("monitor type", "2D X-normal"),
197 | ("x", 1.45e-6), ("y", -0.75e-6),("z",0),
198 | ("y span", 0.5e-6),("z span",0.4e-6),
199 | ("override global monitor settings", True),("frequency points",1)]))
200 |
201 |
202 | # pattern生成
203 | rows, columns = size[0], size[1]
204 | mode.addstructuregroup(name="666")
205 | x_span = 2.6e-6 / columns
206 | y_span = 2.6e-6 / rows
207 | for row in range(rows):
208 | for column in range(columns):
209 | #模型在放置之后,默认选择的就是这个模型,就像下面这里,放置矩形之后可以直接将其加入到模型组之中,不用重新选择
210 | mode.addrect(x=-1.3e-6 + x_span / 2 + column * x_span, x_span=x_span,
211 | y=1.3e-6 - y_span / 2 - row * y_span, y_span=y_span,
212 | z=0, z_span=0.22e-6, name=str(row) + "r" + str(column) + "c",
213 | material="etch")
214 | mode.addtogroup("666")
215 |
216 | ```
217 | 程序中的注释写的应该很详细了,本来想说点什么的,但是感觉说不出话……各位要是有什么问题,记得提出issue,我会尽力解答
218 |
219 |
220 | 接下来是另外两个函数:
221 |
222 | ```
223 | def change_pattern(mode,pattern_matrix):
224 | #先更改到布局模式
225 | mode.switchtolayout()
226 |
227 | #这里定义了一个双向字典,换成人话来说就是定义了一个一对一的表,通过这个表我们能够查询1,0和对对应材料的关系
228 | pattern_dic=bidict({
229 | "Si (Silicon) - Palik":1,
230 | "etch":0
231 | })
232 |
233 | # 两个for循环嵌套,更改每个离散网格内部的材料,(这里没想到一个更优美的解决方案……)
234 | for row in range(pattern_matrix.shape[0]):
235 | for column in range(pattern_matrix.shape[1]):
236 | mode.select("666::"+str(row)+"r"+str(column)+"c")
237 |
238 | #可以通过这种方式获取对象的属性
239 | pix = mode.getObjectBySelection()
240 | material_name=pix.material
241 |
242 | #根据目标矩阵查询是否需要更改对象的材料
243 | if pattern_dic[material_name]!=pattern_matrix[row][column]:
244 | pix.material=pattern_dic.inverse[pattern_matrix[row][column]]
245 |
246 | def get_result(mode):
247 | #这里的.squeeze()方法意思是删除多余的维度,如把(2,3,1,3)变为(2,3,3),方便后续处理
248 | t1 = mode.getresult("T1", "E")["E"].squeeze()
249 | t2 = mode.getresult("T2", "E")["E"].squeeze()
250 | #这里a,b是两个监视器的电场幅值,即xyz方向的平方相加开根
251 | a = np.sqrt(np.sum(np.power(np.abs(t1), 2), axis=1))
252 | b = np.sqrt(np.sum(np.power(np.abs(t2), 2), axis=1))
253 | return a,b
254 |
255 | ```
256 |
257 | 应该挺简单的……也说不出什么话……
258 |
259 | ## 结语
260 |
261 | 根据lumerical官方的说法,python中的方法和他们自带的脚本语言使用方式和命名都相同,如python中的`fdtd.addpower()`对应脚本语言中的`addpower;` https://support.lumerical.com/hc/en-us/articles/360034404534-addpower
262 |
263 | 更详细的方法查询可以参考[关于函数、方法的查询](附录.md#关于函数、方法的查询)
264 |
265 |
--------------------------------------------------------------------------------
/docs/前言.md:
--------------------------------------------------------------------------------
1 | # 前言
2 |
3 | 这个仓库的作用主要有两个:
4 | 1. 记录、备份lumerical 与python交互的技巧和笔记。
5 | 2. 整理组内常用的拓扑优化算法,并用py重构,以提升工作效率。
6 | * 将常用函数整合,附以重要的参数和例子说明
7 |
8 |
9 | 剩下的还没想好,欢迎提issue和pr。
--------------------------------------------------------------------------------
/docs/安装.md:
--------------------------------------------------------------------------------
1 | # 安装
2 |
3 | 安装主要分为三个部分:
4 | 1. lumerical的安装
5 | 2. python 环境的安装
6 | 3. python 联合 lumerical的api的初始环境设置
7 |
8 |
9 | ## lumerical
10 | 根据lumerical官方的说法: https://support.lumerical.com/hc/en-us/articles/360037824513-Python-API-overview
11 |
12 |
13 |
14 | 为了能够正常使用python的接口,我们需要三个条件:
15 |
16 | 1. 自动化python api证书
17 | 2. 2019a R3 或者更新的lumerical 软件版本
18 | 3. 在Linux上:为支持的Linux系统运行bashshell的gnome终端
19 |
20 | ***其中最主要的,就是需要2019a R3版本以上的软件。***
21 |
22 | 这里不会提供下载方式,可以在大学内部的网站进行下载:(蝴蝶、byr什么的)
23 |
24 | 安装并激活之后,可以从下图中查看python api是否激活(这里以mode为例):
25 |
26 | 
27 |
28 |
29 |
30 | ## python
31 |
32 | python的环境配置有很多种,每个人的习惯都不同,所以这里仅简要写一下个人配置的环境
33 |
34 | 本人的环境是:win10 + miniconda + pycharm + jupyter notebook
35 |
36 | 解释一下,做大型工程时,主要使用pycharm,做小型测试和数据可视化的时候,则主要使用jupyter。
37 |
38 |
39 | ## python+lumerical环境结合
40 |
41 | lumerical公司提供的python api接口为软件自带的一个py文件,我们只需要在使用中能够导入就行。
42 |
43 | 假设你的lumerical安装路径在C盘,则python文件的路径为"C:\Program Files\Lumerical\v202\api\python\lumapi.py"
44 | > 路径中的v202是版本号,各位看需进行更改
45 |
46 | 那么如何将这个文件导入呢?
47 |
48 | 这里提供一个一劳永逸的方法:自定义一个pth文件,这样python就能直接`import lumapi`了
49 |
50 | 方法如下:
51 |
52 | 假设你的lumapi安装在c盘,miniconda中的虚拟环境叫做fdtd,并安装在g盘,那么
53 |
54 | 1. 在`G:\miniconda\envs\fdtd\Lib\site-packages`路径下新建`lumapi.pth`文件,内容为`C:\Program Files\Lumerical1\v202\api\python`
55 | 2. 在编程环境中激活虚拟环境fdtd,输入
56 |
57 | ```
58 | import sys
59 | print('\n'.join(sys.path))
60 |
61 | G:\miniconda\envs\fdtd\python38.zip
62 | G:\miniconda\envs\fdtd\DLLs
63 | G:\miniconda\envs\fdtd\lib
64 | G:\miniconda\envs\fdtd
65 | G:\miniconda\envs\fdtd\lib\site-packages
66 | G:\Program Files\Lumerical1\v202\api\python
67 | G:\miniconda\envs\fdtd\lib\site-packages\win32
68 | G:\miniconda\envs\fdtd\lib\site-packages\win32\lib
69 | G:\miniconda\envs\fdtd\lib\site-packages\Pythonwin
70 | ```
71 |
72 | 就能够看到fdtd这个虚拟环境已经成功将lumerical的python路径导入了。
73 |
74 |
75 | ## 结尾
76 | 如果上述安装全都没有出问题,现在就能够开始仿真了。
77 |
78 | 打开你熟悉的py编程环境,尝试输入一下代码并保存运行,看看效果吧:
79 |
80 | ```
81 | import lumapi
82 |
83 | mode = lumapi.MODE()
84 | mode.addrect(x=0, y=0.0, z=-1.11e-6,x_span=2e-5,y_span=1e-5,z_span=2e-6,name="box",material="SiO2 (Glass) - Palik")
85 | input()
86 | ```
87 |
88 | **注意! lumapi依赖于numpy库,所以如果导入报错了,则需要在环境中另外安装numpy!**
89 |
90 | 接下来会写如何使用python api完全代替图形化的操作,包括多线程、会话管理这些。
--------------------------------------------------------------------------------
/docs/测试.md:
--------------------------------------------------------------------------------
1 | # latex测试
2 | $$
3 | \left(\begin{array}{l} c t^{\prime} \\ x^{\prime} \\ y^{\prime} \\ z^{\prime} \end{array}\right)=\left(\begin{array}{cccc} \gamma & -\gamma \beta & 0 & 0 \\ -\gamma \beta & \gamma & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right)\left(\begin{array}{l} c t \\ x \\ y \\ z \end{array}\right)
4 | $$
5 |
6 |
7 | # 代码copy测试
8 |
9 | ```
10 | print("hello python")
11 |
12 | ```
--------------------------------------------------------------------------------
/docs/附录.md:
--------------------------------------------------------------------------------
1 | # 关于python中的包管理
2 |
3 | python中的包管理主要有两种工具,分别是pip和conda,接下来分别介绍:
4 |
5 | * conda:其中conda为anaconda或miniconda特有的包管理工具。
6 | * 优点:除了能够安装普通python包之外,还能够一并安装依赖的其他语言的二进制文件。
7 | * 缺点:有些包是社区维护,并没有更新到最新版;有些包没有。
8 | * 推荐使用方式:安装numpy、pytorch、scipy这些科学计算包时
9 |
10 | * pip:python自带的官方包管理工具。
11 | * 优点:官方维护,一些比较小众的工具包在上面可以找到,conda则没有
12 | * 缺点:当包依赖于其他外部库时、或者有平台限制时,可能会安装失败(TensorFlow这种……)
13 | * 推荐使用方式:bidict、faker这些工具轮子库
14 |
15 | ## 更换下载源
16 | * conda:[清华官方说明](https://mirror.tuna.tsinghua.edu.cn/help/anaconda/)
17 |
18 | * pip :本人比较懒,只有在每次conda装不上的时候才使用pip,所以每次pip的时候都手动指定安装的代理,这里就用例子来说明:
19 |
20 | ```
21 | # 例如我们要安装bidict
22 | pip install bidict -i https://pypi.tuna.tsinghua.edu.cn/simple
23 | ```
24 |
25 | ## 包安装方式
26 | * conda:在更改过软件源之后,打开命令行(cmd)
27 |
28 | ```
29 | #激活对应的虚拟环境
30 | conda activate fdtd
31 |
32 | #开始安装
33 | conda install matplotlib
34 | ```
35 |
36 | * pip:
37 |
38 | ```
39 | # 例如我们要安装bidict
40 | pip install bidict -i https://pypi.tuna.tsinghua.edu.cn/simple
41 | ```
42 |
43 | # 关于函数、方法的查询
44 | 根据lumerical官方的说法,python中的方法和他们自带的脚本语言使用方式和命名都相同,如python中的`fdtd.addpower()`对应脚本语言中的`addpower;` https://support.lumerical.com/hc/en-us/articles/360034404534-addpower
45 |
46 | 但还是存在一些微小的差异,那么我们如何查询呢?
47 |
48 | 我们可以借鉴脚本语言中的`?set`命令 https://support.lumerical.com/hc/en-us/articles/360034928773-set-Script-command
49 |
50 | 举个例子:我们想设置监视器T1的长宽,但是不知道对应的变量名字叫啥,我们就可以:
51 |
52 | ```
53 | #我们以例程中的结果为例,大家可以将例程中的代码放在jupyter中跑,以免跑完后程序关闭
54 |
55 | mode.select("T1") #选择T1
56 | print(mode.set()) #打印出能够设置的参数
57 |
58 | #以下是对应的输出
59 | Nyquist limit
60 | actual sampling
61 | apodization
62 | apodization center
63 | apodization freq width
64 | apodization time width
65 | custom frequency samples
66 | delta
67 | desired sampling
68 | down sample X
69 | down sample Y
70 | down sample Z
71 | down sample time
72 | enabled
73 | frequency center
74 | frequency points
75 | frequency span
76 | maximum frequency
77 | maximum wavelength
78 | min sampling per cycle
79 | minimum frequency
80 | minimum wavelength
81 | monitor type
82 | name
83 | output Ex
84 | output Ey
85 | output Ez
86 | output Hx
87 | output Hy
88 | output Hz
89 | output Px
90 | output Py
91 | output Pz
92 | output power
93 | override advanced global monitor settings
94 | override global monitor settings
95 | partial spectral average
96 | record data in pml
97 | sample spacing
98 | spatial interpolation
99 | standard fourier transform
100 | total spectral average
101 | type
102 | use relative coordinates
103 | use source limits
104 | use wavelength spacing
105 | wavelength center
106 | wavelength span
107 | x
108 | x max
109 | x min
110 | x span
111 | y
112 | y max
113 | y min
114 | y span
115 | z
116 | z max
117 | z min
118 | z span
119 | ```
120 |
121 | 能看到有x,y,z的设置,于是我们就能这样设置参数了:
122 |
123 | ```
124 | mode.addpower(properties=OrderedDict([("name", "T1"), ("monitor type", "2D X-normal"),
125 | ("x", 1.45e-6), ("y", 0.75e-6),("z",0),
126 | ("y span", 0.5e-6),("z span",0.4e-6),
127 | ("override global monitor settings", True),("frequency points",1)]))
128 | ```
--------------------------------------------------------------------------------
/src/gen_data/main.py:
--------------------------------------------------------------------------------
1 | import lumapi
2 | import numpy as np
3 | from collections import OrderedDict
4 | import os
5 | from bidict import bidict
6 |
7 |
8 | row_num = 10
9 | column_num = 10
10 | workers = 2
11 | def init_base(mode,size=(2,2)):
12 | mode.switchtolayout()
13 | # 基底生成
14 | mode.importmaterialdb("fdtd_files/material.mdf")
15 | mode.addrect(x=0, y=0.0, z=-1.11e-6,x_span=2e-5,y_span=1e-5,z_span=2e-6,name="box",material="SiO2 (Glass) - Palik")
16 | mode.addrect(x=0, y=0.0, z=0,x_span=2.6e-6,y_span=2.6e-6,z_span=0.22e-6,name="si",material="si")
17 | mode.addrect(x=-5.15e-6, y=0.0, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="in",
18 | material="si")
19 | mode.addrect(x=5.15e-6, y=0.75e-6, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="out1",
20 | material="si")
21 | mode.addrect(x=5.15e-6, y=-0.75e-6, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="out2",
22 | material="si")
23 | mode.addmesh(x=0, y=0, z=0, x_span=2.6e-6, y_span=2.6e-6, z_span=0.22e-6, name="mesh",
24 | dx=0.02e-6,dy=0.02e-6,dz=0.02e-6,)
25 | mode.addvarfdtd(x=0, y=0, z=0,x_span=4e-6, y_span=4e-6, z_span=0.8e-6,simulation_time=1000e-15,x0=-1.48565e-6)
26 |
27 | source_props = OrderedDict([("name", "source"), ("injection axis", "x"),
28 | ("x", -1.7e-6), ("y", 0),("y span", 2e-6),
29 | ("selected mode number",2),
30 | ("center wavelength",1.5e-6),("wavelength span",0.01e-6),
31 | ("optimize for short pulse", 1)
32 | ])
33 | mode.addmodesource(properties=source_props)
34 |
35 | mode.addpower(properties=OrderedDict([("name", "T1"), ("monitor type", "2D X-normal"),
36 | ("x", 1.45e-6), ("y", 0.75e-6),("z",0),
37 | ("y span", 0.75e-6),("z span",0.4e-6),
38 | ("override global monitor settings", True),("frequency points",1)]))
39 | mode.addmodeexpansion(properties=OrderedDict([
40 | ("name", "M1"),
41 | ("x", 1.65e-6),
42 | ("y", 0.75e-6),
43 | ("y span", 0.75e-6),
44 | ]))
45 | mode.setexpansion("input", "T1")
46 |
47 | mode.addpower(properties=OrderedDict([("name", "T2"), ("monitor type", "2D X-normal"),
48 | ("x", 1.45e-6), ("y", -0.75e-6),("z",0),
49 | ("y span", 0.75e-6),("z span",0.4e-6),
50 | ("override global monitor settings", True),("frequency points",1)]))
51 |
52 | mode.addmodeexpansion(properties=OrderedDict([
53 | ("name", "M2"),
54 | ("x", 1.65e-6),
55 | ("y", 0.75e-6),
56 | ("y span", 0.75e-6),
57 | ]))
58 | mode.setexpansion("input", "T2")
59 |
60 | mode.addpower(properties=OrderedDict([("name", "all"), ("monitor type", "2D Z-normal"),
61 | ("x", 0), ("y", 0), ("z", 0),
62 | ("x span", 2.6e-6), ("y span", 2.6e-6),
63 | ("override global monitor settings", True), ("frequency points", 1)]))
64 | # pattern生成
65 | rows, columns = size[0], size[1]
66 | mode.addstructuregroup(name="666")
67 | x_span = 2.6e-6 / columns
68 | y_span = 2.6e-6 / rows
69 | for row in range(rows):
70 | for column in range(columns):
71 | mode.addrect(x=-1.3e-6 + x_span / 2 + column * x_span, x_span=x_span,
72 | y=1.3e-6 - y_span / 2 - row * y_span, y_span=y_span,
73 | z=0, z_span=0.22e-6, name=str(row) + "r" + str(column) + "c",
74 | material="etch")
75 | mode.addtogroup("666")
76 |
77 | def change_pattern_(old_pattern_matrix=np.zeros([row_num,column_num])):
78 | def change(mode,new_pattern_matrix):
79 | nonlocal old_pattern_matrix
80 | mode.switchtolayout()
81 | pattern2change = np.argwhere(old_pattern_matrix!=new_pattern_matrix)
82 | pattern_dic = bidict({
83 | "si": 1,
84 | "etch": 0
85 | })
86 | for row,column in pattern2change:
87 | mode.select("666::"+str(row)+"r"+str(column)+"c")
88 | pix = mode.getObjectBySelection()
89 | pix.material=pattern_dic.inverse[new_pattern_matrix[row][column]]
90 | old_pattern_matrix = new_pattern_matrix
91 | return change
92 |
93 | def fom(mode):
94 | t1 = mode.getresult("T1", "E")["E"].squeeze()
95 | t2 = mode.getresult("T2", "E")["E"].squeeze()
96 | a = np.sqrt(np.sum(np.power(np.abs(t1), 2), axis=1))
97 | b=np.sqrt(np.sum(np.power(np.abs(t2), 2), axis=1))
98 | return (a-b).max()
99 |
100 |
101 | mode = lumapi.MODE()
102 | init_base(mode, size=(row_num, column_num))
103 | mode.save("fdtd_files/base"+str(row_num)+"_"+str(column_num)+".lms")
104 | change_pattern = change_pattern_()
105 | fileds=[]
106 | pattern=[]
107 | for i in range(2):
108 | for i in range(workers):
109 | pattern_matrix = np.random.randint(0, 2, (row_num // 2, column_num))
110 | pattern_matrix = np.concatenate([np.flip(pattern_matrix, axis=0), pattern_matrix], axis=0)
111 | pattern.append(pattern_matrix)
112 | change_pattern(mode, pattern_matrix)
113 | currentfilename = os.getcwd() + "/fdtd_files/temp/temp_" + str(i) + ".lms"
114 | mode.save(currentfilename)
115 | mode.addjob(currentfilename)
116 |
117 | mode.runjobs()
118 |
119 | for i in range(workers):
120 | currentfilename = os.getcwd() + "/fdtd_files/temp/temp_" + str(i) + ".lms"
121 | mode.load(currentfilename)
122 | t1 = mode.getresult("M1", "expansion for input")["T_forward"].squeeze()
123 | fileds.append(
124 | np.einsum("ijk->jik",np.concatenate(
125 | [mode.getresult("all", "E")["E"].squeeze(), mode.getresult("all", "H")["H"].squeeze()]
126 | ,axis=2))[:51,:])
127 |
128 |
129 |
130 | fileds=np.array(fileds)
131 | pattern = np.array(pattern)
132 | a=input()
133 | np.savez("data/data.npy",pattern=pattern, fileds=fileds)
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/src/material.mdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Photonic-AI-Communication/lumerical-python-script/ba1b44ea665e7b0ec347970d67f1dd18bd2170f7/src/material.mdf
--------------------------------------------------------------------------------
/src/transpose/gen_data.py:
--------------------------------------------------------------------------------
1 | from initbase import init_base,change_pattern,fom
2 | import lumapi
3 | import numpy as np
4 | from collections import OrderedDict
5 | import os
6 | from bidict import bidict
7 |
8 | row_num = 5
9 | column_num = 5
10 | mode = lumapi.MODE()
11 | init_base(mode, size=(row_num, column_num))
12 | mode.save("fdtd_files/base"+str(row_num)+"_"+str(column_num)+".lms")
13 |
14 | pattern_matrix = np.random.randint(0, 2, (row_num, column_num))
15 | change_pattern(mode,pattern_matrix)
16 | mode.run()
17 | best_result=fom(mode)
18 |
19 | t1 = mode.getresult("M1","expansion for input")["T_forward"].squeeze()
20 | print(t1)
21 | a=input()
--------------------------------------------------------------------------------
/src/transpose/initbase.py:
--------------------------------------------------------------------------------
1 | import lumapi
2 | import numpy as np
3 | from collections import OrderedDict
4 | import os
5 | from bidict import bidict
6 |
7 |
8 | def init_base(mode,size=(2,2)):
9 | mode.switchtolayout()
10 | # 基底生成
11 | mode.importmaterialdb("fdtd_files/material.mdf")
12 | mode.addrect(x=0, y=0.0, z=-1.11e-6,x_span=2e-5,y_span=1e-5,z_span=2e-6,name="box",material="SiO2 (Glass) - Palik")
13 | mode.addrect(x=0, y=0.0, z=0,x_span=2.6e-6,y_span=2.6e-6,z_span=0.22e-6,name="si",material="si")
14 | mode.addrect(x=-5.15e-6, y=0.0, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="in",
15 | material="si")
16 | mode.addrect(x=5.15e-6, y=0.75e-6, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="out1",
17 | material="si")
18 | mode.addrect(x=5.15e-6, y=-0.75e-6, z=0, x_span=7.7e-6, y_span=0.5e-6, z_span=0.22e-6, name="out2",
19 | material="si")
20 | mode.addmesh(x=0, y=0, z=0, x_span=2.6e-6, y_span=2.6e-6, z_span=0.22e-6, name="mesh",
21 | dx=0.02e-6,dy=0.02e-6,dz=0.02e-6,)
22 | mode.addvarfdtd(x=0, y=0, z=0,x_span=4e-6, y_span=4e-6, z_span=0.8e-6,simulation_time=1000e-15,x0=-1.48565e-6)
23 |
24 | source_props = OrderedDict([("name", "source"), ("injection axis", "x"),
25 | ("x", -1.7e-6), ("y", 0),("y span", 2e-6),
26 | ("selected mode number",2),
27 | ("center wavelength",1.5e-6),("wavelength span",0.01e-6),
28 | ("optimize for short pulse", 1)
29 | ])
30 | mode.addmodesource(properties=source_props)
31 |
32 | mode.addpower(properties=OrderedDict([("name", "T1"), ("monitor type", "2D X-normal"),
33 | ("x", 1.45e-6), ("y", 0.75e-6),("z",0),
34 | ("y span", 0.75e-6),("z span",0.4e-6),
35 | ("override global monitor settings", True),("frequency points",1)]))
36 | mode.addmodeexpansion(properties=OrderedDict([
37 | ("name", "M1"),
38 | ("x", 1.65e-6),
39 | ("y", 0.75e-6),
40 | ("y span", 0.75e-6),
41 | ]))
42 | mode.setexpansion("input", "T1")
43 |
44 | mode.addpower(properties=OrderedDict([("name", "T2"), ("monitor type", "2D X-normal"),
45 | ("x", 1.45e-6), ("y", -0.75e-6),("z",0),
46 | ("y span", 0.75e-6),("z span",0.4e-6),
47 | ("override global monitor settings", True),("frequency points",1)]))
48 |
49 | mode.addmodeexpansion(properties=OrderedDict([
50 | ("name", "M2"),
51 | ("x", 1.65e-6),
52 | ("y", 0.75e-6),
53 | ("y span", 0.75e-6),
54 | ]))
55 | mode.setexpansion("input", "T2")
56 |
57 | mode.addpower(properties=OrderedDict([("name", "all"), ("monitor type", "2D Z-normal"),
58 | ("x", 0), ("y", 0), ("z", 0),
59 | ("x span", 2.6e-6), ("y span", 2.6e-6),
60 | ("override global monitor settings", True), ("frequency points", 1)]))
61 | # pattern生成
62 | rows, columns = size[0], size[1]
63 | mode.addstructuregroup(name="666")
64 | x_span = 2.6e-6 / columns
65 | y_span = 2.6e-6 / rows
66 | for row in range(rows):
67 | for column in range(columns):
68 | mode.addrect(x=-1.3e-6 + x_span / 2 + column * x_span, x_span=x_span,
69 | y=1.3e-6 - y_span / 2 - row * y_span, y_span=y_span,
70 | z=0, z_span=0.22e-6, name=str(row) + "r" + str(column) + "c",
71 | material="etch")
72 | mode.addtogroup("666")
73 |
74 | def change_pattern(mode,pattern_matrix):
75 | mode.switchtolayout()
76 | pattern_dic=bidict({
77 | "si":1,
78 | "etch":0
79 | })
80 | for row in range(pattern_matrix.shape[0]):
81 | for column in range(pattern_matrix.shape[1]):
82 | mode.select("666::"+str(row)+"r"+str(column)+"c")
83 | pix = mode.getObjectBySelection()
84 | material_name=pix.material
85 | if pattern_dic[material_name]!=pattern_matrix[row][column]:
86 | pix.material=pattern_dic.inverse[pattern_matrix[row][column]]
87 |
88 | def fom(mode):
89 | t1 = mode.getresult("T1", "E")["E"].squeeze()
90 | t2 = mode.getresult("T2", "E")["E"].squeeze()
91 | a = np.sqrt(np.sum(np.power(np.abs(t1), 2), axis=1))
92 | b=np.sqrt(np.sum(np.power(np.abs(t2), 2), axis=1))
93 | return (a-b).max()
94 |
95 |
--------------------------------------------------------------------------------