用python编写的三维电磁fdtd模拟器

fdtd的Python项目详细描述


python三维fdtd模拟器

用python编写的三维电磁fdtd模拟器。FDTD模拟器具有 可选Pythorch后端,在GPU上启用FDTD模拟。

注意:该库正在建设中。只实现了一些最小的特性 API可能会发生很大变化。

安装

fdtd-库可以用pip安装:

pip install fdtd

可以通过克隆存储库来安装开发版本

git clone http://github.com/flaport/fdtd

并将其与pip链接

pip install -e fdtd

依赖关系

  • 巨蟒3.6+
  • 努比
  • matplotlib
  • 全面质量管理
  • Pythorch(可选)

贡献

图书馆仍处于发展的早期阶段,但所有的改进 或添加(例如新对象、源或检测器)是受欢迎的。 请提出拉取请求。

库简介

进口

fdtd库简单地导入如下:

importfdtd

设置后端

fdtd库允许选择后端。后端是 默认为一个,但也有几个额外的pytorch后端:

  • "numpy"(默认为float64数组)
  • "torch"(默认为float64张量)
  • "torch.float32"
  • "torch.float64"
  • "torch.cuda"(默认为float64张量)
  • "torch.cuda.float32"
  • "torch.cuda.float64"

例如,这是如何选择"torch"后端:

fdtd.set_backend("torch")

一般来说,对于标准的CPU计算,首选使用"numpy"后端 具有"float64"精度。通常,精度总是 然而,对于fdtd模拟来说,优先于"float32",但是,"float32"可能 显著提高性能。

"CUDA"后端仅适用于带有GPU的计算机。

FDTD网格

FDTD网格定义了模拟区域。

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)

网格是由其形状定义的,它只是数字类型的3d元组 (整数或浮点数)。如果形状是浮点数,它表示宽度, 网格的高度和长度(以米为单位)。如果形状是整数,那么 表示网格的宽度、高度和长度 网格间距。在内部,这些数字将转换为三个整数: grid.nxgrid.nygrid.nz

可以给出网格间距。出于稳定性考虑,建议 选择至少比最小值小10倍的网格间距 网格中的波长。这意味着对于包含 波长1550nm和折射率3.1的材料, 建议的最小网格间距50pm

对于介电常数和磁导率 形状

  • (grid.nx,grid.ny,grid.nz)
  • (grid.nx,grid.ny,grid.nz,1)
  • (grid.nx,grid.ny,grid.nz,3)

是应该的。在最后一种情况下,形状意味着 每个主轴的介电常数(所谓的单轴双轴 材料)。在内部,这些变量将被转换(为了性能 原因)它们的逆网格。介电常数逆数组和 网格.反渗透性形状数组(grid.nx,grid.ny,grid.nz,3)。它 可以在生成网格后更改这些数组。

最后,网格的courant_数决定了 模拟的时间步以及网格的网格间距。如果不给, 它被选为courant friedrichs lewy允许的最大数目 条件: 1用于1d模拟,1/√2用于2d模拟,1/√3用于3d 模拟(维度将由网格的形状导出)。为了 出于稳定性原因,建议不要更改此值。

grid=fdtd.Grid(shape=(25e-6,15e-6,1),# 25um x 15um x 1 (grid_spacing) --> 2D FDTD)print(grid)
Grid(shape=(161,97,1), grid_spacing=1.55e-07, courant_number=0.70)

将对象添加到网格

另一个选项是在 网格是将对象添加到网格中。

# signaturefdtd.Object(permittivity:Tensorlike,name:str=None)

对象使用修改后的更新公式定义网格的一部分,允许 引入例如吸收材料或双轴材料 轴之间的混合通过pockels系数或许多 更多。在这种情况下,我们将创建一个不同于 它所在的网格。

就像对于网格一样,对象期望介电常数是浮点数或 下列可能形状的数组

  • (obj.nx,obj.ny,obj.nz)
  • (obj.nx,obj.ny,obj.nz,1)
  • (obj.nx,obj.ny,obj.nz,3)

请注意,值obj.nxobj.nyobj.nz没有给 对象构造函数。它们是从网格中的位置派生出来的:

pip install fdtd
0

这里发生了几件事。首先,物体被赋予空间 网格中的[11:32,30:84,0]。因为给了这个空间,物体 nxnynz自动设置。此外,通过提供 对象,此名称将在网格中可用:

pip install fdtd
1
pip install fdtd
2

第二个对象可以添加到网格:

pip install fdtd
3

这里,选择了一个带浮点数的切片。这些漂浮物 在对象注册过程中替换为整数nxnynz。 由于对象没有收到名称,因此该对象将不能作为 网格的属性。但是,它仍然可以通过网格.objects获得 清单:

pip install fdtd
4
pip install fdtd
5

此列表按以下顺序存储所有对象(即fdtd.object类型) 它们被添加到网格中。

将源添加到网格

与向网格中添加对象类似,fdtd.linesource也可以是 新增:

pip install fdtd
6

而且就像fdtd.objectfdtd.sourcesize一样,fdtd.source的大小由它的 网格上的位置:

pip install fdtd
7

但是,需要注意的是,在这种情况下,会将linesource添加到 网格,即源跨越由切片定义的立方体的对角线。 在内部,这些切片将转换为列表,以确保此行为:

pip install fdtd
8
pip install fdtd
9

注意,还可以提供列表来索引第一个网格 地点。此功能可用于创建任意 形状:

在网格中添加检测器

git clone http://github.com/flaport/fdtd
0

向网格中添加检测器的工作原理与添加源相同

git clone http://github.com/flaport/fdtd
1
git clone http://github.com/flaport/fdtd
2
git clone http://github.com/flaport/fdtd
3

添加网格边界

git clone http://github.com/flaport/fdtd
4

不过,原则上有一个对象、源和探测器来模拟 足够进行fdtd模拟,还需要定义网格边界。 以防止字段被反射。其中一个界限可以是 网格中添加了一个完全匹配的层 层或pml。这些 基本上是吸收边界。

git clone http://github.com/flaport/fdtd
5

网格摘要

可以通过打印ou来显示网格的简单摘要t网格:

git clone http://github.com/flaport/fdtd
6
git clone http://github.com/flaport/fdtd
7

运行模拟

运行模拟就像使用grid.run方法一样简单。

git clone http://github.com/flaport/fdtd
8

与网格中的长度一样,模拟的总时间。 可以指定为整数(时间步数)或浮点(in 秒)。

git clone http://github.com/flaport/fdtd
9

网格可视化

让我们想象一下网格。这可以通过网格来完成。visualize方法:

pip install -e fdtd
0

默认情况下,此方法将可视化网格中的所有对象,以及 在当前时间步的某个xyz-平面上通电。通过 设置show=false,可以禁用 matplotlib图像。

pip install -e fdtd
1

png

背景

尽快解释麦克斯韦方程的fdtd离散化。

更新公式

电磁fdtd求解器求解含时maxwell方程组

pip install -e fdtd
2

这两个方程分别称为安培定律法拉第定律

在这些方程中,ε和μ是相对介电常数和磁导率张量 分别是。ε0和μ0是真空介电常数和磁导率 平方根可以分别被吸收到e和h中,使得e:=√ε0*e 以及h:=√μ0*h

这样,麦克斯韦方程可以写成更新方程:

pip install -e fdtd
3

电场和磁场可以在网格上离散 交错的yee坐标,在3d中如下所示:

三维网格离散化

根据yee离散化算法,本质上有两种类型 网格上的字段数:e-键入整数网格位置上的字段和h-键入 半整数网格位置上的字段。

这些交错坐标的美妙之处在于它们使 电场和磁场旋度的书写方法:旋度 h-type字段将是e-type字段,反之亦然。

这样,e的旋度可以写成

pip install -e fdtd
4

这可以用数组切片高效地编写(注意 (1/du)被省略:

pip install -e fdtd
5

h的旋度可以用类似的方法获得(再次注意 (1/du)被省略:

pip install -e fdtd
6

更新公式现在可以重写为

pip install -e fdtd
7

数字(c*dt/du)是一个无量纲参数,称为courant数。为了 稳定性原因,courant数应始终小于1/√d,且d 模拟的维度。这可以直观地理解为 这些信息在网格中的传播速度应该总是比光速慢。 在这里描述的fdtd方法中,信息只能传递到相邻的网格。 细胞(通过卷曲的应用)。因此,需要d时间步才能 在ad维度立方体的对角线上移动(在2d中为正方形,在3d中为立方体),然后 然后,courant条件自动从以下事实开始 对角线是1/√d

这将得到fdtd算法的最终更新方程:

pip install -e fdtd
8

这也是它的实现方式:

pip install -e fdtd
9

来源

安培定律可以更新为包含电流密度:

importfdtd
0

再次进行通常的替换sc:=c*dt/due:=√ε0*eh:=√μ0*h,则 可以修改更新公式以包含current密度:

importfdtd
1

进行最后一次替换es:=-dt*inv(ε)*j/√ε0允许我们将其写入 非常干净的方式:

importfdtd
2

其中,es定义为电场源项。

通常还可以定义磁场源项 由磁电流密度导出。以同样的方式, 法拉第的更新方程可以重写为

importfdtd
3
importfdtd
4

有损介质

当材料具有电导率σe时,传导电流将确保介质是有损耗的。带传导电流的安培定律变为

importfdtd
5

进行通常的替换,这将变为:

importfdtd
6

这个更新方程依赖于半整数时间步上的电场(a磁场时间步)。我们需要做一个替换,将电场插值到这个时间步:

importfdtd
7

其中,在替换后σ:=inv(ε)*σe/ε0产生新的更新方程:

importfdtd
8

如果我们想跟踪吸收的能量:

请注意,介电常数张量ε越复杂,则 算法将是。因此,有时通过引入(非物理)磁导率将吸收转移到磁畴是正确的决定,因为 渗透张量μ通常等于1。

代换后,得到磁场更新方程:

importfdtd
9

能量密度和poynting矢量

电磁能量密度可由

fdtd.set_backend("torch")
0

在进行上述替换时,这将变为模拟单位:

fdtd.set_backend("torch")
1

poynting向量由

fdtd.set_backend("torch")
2

在模拟单元中变成

fdtd.set_backend("torch")
3

es引入的能量可以通过跟踪能量密度的变化来获得

fdtd.set_backend("torch")
4

这也可以从poyntings能量守恒定律中得到:

fdtd.set_backend("torch")
5

其中第一项只描述能量在体积中的再分配,第二项描述能量在体积中的再分配。 电流密度产生的能量。

注:虽然它是非物理的,但也可以引入磁源。这个能量源将引入以下能量:

fdtd.set_backend("torch")
6

由于μ张量通常等于1,使用磁源项通常更有效。

类似地,还可以通过以下方式跟踪导电性引起的吸收能量:

fdtd.set_backend("torch")
7

或者,如果我们想跟踪磁性吸收的能量,磁传导率:

fdtd.set_backend("torch")
8

能量密度中的电项和磁项通常大小相同。因此,通过引入a磁导率σm,可以吸收相同数量的能量 如果:

fdtd.set_backend("torch")
9

边界条件

周期边界条件

假设我们想要沿x方向的周期性边界条件,那么我们必须 确保xlowxhigh处的字段相同。必须强制执行 执行更新公式后:

请注意,电场e取决于旋度h,这意味着 e的第一个索引将不会通过更新公式进行更新。 这些指标需要通过周期边界条件来设定。 具体来说:e[0]需要设置为等于e[-1]。对于磁场, 逆是真的:h依赖于curl,这意味着它的最后一个索引 不会被设置。这必须通过边界条件来实现:h[-1]需要 设为h[0]

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
0

完全匹配的层

完全匹配的层(pml)是 在fdtd网格中引入吸收边界条件。 PML是电网中阻抗匹配的吸收区域。结果发现 为了保持阻抗匹配条件,PML只能在 一个单一的方向。这就是为什么PML实际上是一种非物理材料。

考虑ez组件的安培定律,其中通常的替换 e:=√ε0*eh:=√μ0*hσ:=inv(ε)*σe/ε0是 已经介绍:

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
1

这在频域中变为:

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
2

我们可以把这个方程分为x传播波和y传播波:

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
3

我们可以如下定义s-运算符

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
4

一般来说,我们倾向于将稳定因子au和比例因子ku添加到su

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
5

ez的两个方程除以相应的s-运算符后求和

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
6

将其转换回时间域可获得

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
7

其中,sx表示(1/sx)的逆傅里叶变换,[*]表示卷积。 su的表达式[经过一些推导]可以证明如下:

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
8

式中,δ(t)表示狄拉克δ函数,c(t)指数 衰减函数由:

# signaturefdtd.Grid(shape:Tuple[Number,Number,Number],grid_spacing:float=155e-9,permittivity:float=1.0,permeability:float=1.0,courant_number:float=None,)
9

插入此选项将得到:

grid=fdtd.Grid(shape=(25e-6,15e-6,1),# 25um x 15um x 1 (grid_spacing) --> 2D FDTD)print(grid)
0

这可以写成一个更新公式:

grid=fdtd.Grid(shape=(25e-6,15e-6,1),# 25um x 15um x 1 (grid_spacing) --> 2D FDTD)print(grid)
1

其中我们将Фeu定义为

grid=fdtd.Grid(shape=(25e-6,15e-6,1),# 25um x 15um x 1 (grid_spacing) --> 2D FDTD)print(grid)
2

并取v方向上hw的导数,作为更新分量eu的卷积:

grid=fdtd.Grid(shape=(25e-6,15e-6,1),# 25um x 15um x 1 (grid_spacing) --> 2D FDTD)print(grid)
3

这可以重写[经过一些推导]作为更新方程本身:

grid=fdtd.Grid(shape=(25e-6,15e-6,1),# 25um x 15um x 1 (grid_spacing) --> 2D FDTD)print(grid)
4

其中,常数bucu导出为:

grid=fdtd.Grid(shape=(25e-6,15e-6,1),# 25um x 15um x 1 (grid_spacing) --> 2D FDTD)print(grid)
5

电场的最终pml算法现在变成:

  1. 通过使用Ψ-组件的更新方程,更新Фe=[Фex,Фey,Фez]
  2. 以正常方式更新电场
  3. Фe加到电场中。
  4. < > >

    或者作为python代码:

    grid=fdtd.Grid(shape=(25e-6,15e-6,1),# 25um x 15um x 1 (grid_spacing) --> 2D FDTD)print(grid)
    6

    同样的方法也适用于磁场。

    PML的这些更新公式基于Schneider,第11章

    许可证

    ?Floris Laporte-麻省理工学院许可证

    欢迎加入QQ群-->: 979659372 Python中文网_新手群

    推荐PyPI第三方库


热门话题
面向java语句的方法与面向表达式的方法   密码学如何在java中为json对象签名?   是否可以通过java程序知道给定卡夫卡消费群体的消费偏移量?   打印字符时出现java未知问号   java为JFrame设置背景色   在ubuntu中检查java版本时linux权限被拒绝   如何用java创建xml模式   java无法在远程服务器上运行Vaadin应用程序   java智能垃圾收集?   java如何在SpringMVC中设置缓存头?   在unix计算机上运行java应用程序a:>签名以输入内容   Java、Apache Commons配置XML属性   使用ArrayList调用Java未经检查的方法   在文本文件中查找并替换单词(Java GUI)   java Android Studio无法检测到JDK7或更新版本   java从socket的有效负载获取事件消息   安卓中java调用子类方法   java如何通过点击超链接来运行jar文件(Firefox)