MPB使用指南(部分)
20061201日星期五MPB使用指南(部分) MPB使用指南
在这里,我们会展示如何使用MPB进行二维光子晶体能带计算和输出场分布图的整个过程。你可以从中知道MPB如何工作,也可以了解什么样的东西可以用它来 实现。这里所列出的只是一部分,在MPB User Reference里会有更详细的内容。在下一个专题,data analysis tutorial,会有更多的例子,着重数据的分析和可视化。
ctl文件
MPB的使用中,ctl文件是不可缺少的,它的后缀是“ctl”,文件名类似l(你可以用你自己喜欢的名字代替foo)。ctl文件包括了 所要研究的几何结构,要计算的本征矢量的数目,想要输出的东西和其他你想要计算的东西。ctl是用脚本语言来写的,所以它可以写成一系列简单的命令,来设 计几何结构等等。在这个文件中全部是用户输入,循环和其他必须的命令。
不过不用担心,你不须要做一个真正的程序员,因为这些语言都是比较简单的,例如你可以不用按顺序来输入,不用理会空格,可以随便插入说明,也可以不理会其他默认的设置。
ctl文件是执行在libctl库上面的,而libctl也是建立在Scheme语言上。因此,在一个ctl文件中有三种可能的命令和语法:
1. Scheme 是由MIT开发出来的一个强大的程序语言,它的语法很简单:所有的状态量都是以下这个形式,() 。我们要在GUN Guile编译器下运行Scheme。你不必学太多的Scheme来写一个基本的ctl文件,你可以在需要的时候再去查。当然,有兴趣的话,可以参考它 们的主页。
2. libctl 是我们用Guile编写的一个库,它是用来简化Scheme和科学计算软件的接口。libctl设置了一些基本的格式来实现用户接口和定义大量有用的函数。具体参考其主页。
3. MPB 定义了全部的接口,用来实现光子能带的计算。在manual里,会着重说明它的特点。
如果你能去了解一下libctl manual,你会获益非浅,特别是libctl Basic User Experience那一节,这样你就可以知道用户接口是怎样的,Scheme语言大概是怎样的(这个是很有用的),还有一些有用的一般性质。在这里我们 就不再重复了。
那就让我们继续。MPB程序一般是用以下的命令来运行:
unix% l >& foo.out
这样,程序就会读入ctl文件,并且执行,保存数据在foo.out这个文件里(在mpb-ctl / examples / 文件夹里有一些ctl文件的例子)。当然,你也可以直接输入mpb命令,这样就进入了对话模式,你可以继续输入命令然后直接看到结果。
计算第一个能带结构
我们第一个例子是计算由介质棒构成的四方晶格的二维能带。在我们的ctl文件里,我们会首先指明要仿真的几何结构和参数,然后让它运行和输出。
所有的参数都有默认值,每个参数对应着一个Scheme变量,所以我们只须指明哪些是需要修改的。(如果在guile提示符下输入命令:(help) ,程序会列出所有的参数变量和它们的信息)。其中一个参数是 num-bands ,是指明在每个K点要计算的能带的数目。如果你在提示符下输入 num-bands,它会返回当前值:1 ——这个数值太小了,可以加大:
(set! num-bands 8)
这就是我们改变参数的过程(如果你现在输入num-bands,它会显示8)。下一步要做的是(与顺序无关),设置我们想要计算能带的K点。这个参数由变 k-points来决定,它是一个三维矢量,默认值是空的。我们把K点取在四方格子的简约布里渊区的转角处,Gamma,X, M, Gamma
(set! k-points (list (vector3 0 0 0) ; Gamma(vector3 0.5 0 0) ; X(vector3 0.5 0.5 0) ; M(vector3 0 0 0))) ; Gamma
注意我们是怎样建立一个list,还有三个矢量vector3;我们可以分多行输入,还可以在分号后加上注释。一般上,我们也要计算三个方向上的K点的能带,这样才可以得到近似连续的能带图。我们可以调用一个函数来插入K点:
(set! k-points (interpolate 4 k-points))
这个函数可以在每个转角间线性插入4K点;如果我们在提示符下输入k-points,它会显示以下的16个点:
(#(0 0 0) #(0.1 0.0 0.0) #(0.2 0.0 0.0) #(0.3 0.0 0.0) #(0.4 0.0 0.0) #(0.5 0 0) #(0.5 0.1 0.0) #
(0.5 0.2 0.0) #(0.5 0.3 0.0) #(0.5 0.4 0.0) #(0.5 0.5 0)#(0.4 0.4 0.0) #(0.3 0.3 0.0) #(0.2 0.2 0.0) #(0.1 0.1 0.0) #(0 0 0))
如上面描述的那样,当K点(非归一化的)定义在倒格矢上时,程序里全部的空间矢量都是在定义的格点基矢上,而基矢是归一在basis-size长度的。在 这种情况下,我们不必指明格点方向,因为程序默认了格点的单位坐标轴(例如,最常见的四方/立方晶格)(倒格点的矢量也是如此)。下面,我们将会看到如何 改变实空间格点基矢。
现在,我们要设置晶体的几何结构,所以我们先要指明在格点中心的元胞究竟包含什么东西,而变量geometry就是我们需要设置的,它包括了几个对象。在 libctl文件里提到,对象(object)是一个复杂的结构数据类型,它是由状态量( (make type (property1 value1) (property2 value2) ...))产生的。在几何对象里,包含了几种变量:圆柱棒(cylinders, 球体(spheres, 方块(blocks,椭球(ellipsoids),在将来可能会有其他类型。现在,我们想要一个圆柱棒的四方晶格结构,所以我们把一根介质圆柱棒摆在 格点中心:
(set! geometry (list (make cylinder(center 0 0 0) (radius 0.2) (height infinity)(material (make dielectric (epsilon 12))))))在这里,我们设置了介质棒的几个性质。center是在中心,radius
0.2height是无穷。另外一个性质是material,它自己也是一 个对象——我们让它的性质是dielectric,而且介电常数epsilon12。还有一个性质我们可以设置,就是介质棒的轴向,不过我们可以保留默 认,即是在z方向上。
所有的几何对象在表面上是三维的,但是我们要做的是二维仿真,唯一重要的是介质棒和xy平面的交点。换句话说,就是我们要设定晶体的维数。一般上,在我们 定义计算单元的大小时,这项工作已经同时完成了。计算单元的大小是由变量geometry-lattice来决定的,它是lattice类的一个对象。我 们可以设置一些维数为no-size,这样就把这个维度去掉,减少了系统的维数:(set! geometry-lattice (make lattice (size 1 1 no-size)))这里,我们定义了一个1*1的二维单元(默认是四方格子)。这个单元可以由变量resolution来离散化,默认值是10。这个数值对于二维的计算来说比较小,所以我们可以加大:
(set! resolution 32)
那么计算单元就会变成一个32*32的计算网格。从计算的效率来说,最好是把网格设成2的倍数,或者是一些小的数字的倍数(例如:2radius软件,357)。粗略估计,把resolution设成8以上才可以得到一个合理的精度。
至此,我们已经完成了参数的设置,其实还有几个其他的参数,但是在这里我们保留默认值。我们现在就要计算能带了。最简单的方法是输入(run)。因为这是二维计算,所以我们可以分别计算TM模和TE模,这时,我们要输入(run-te)(run-tm)