# Meep Tutorial

Revision as of 02:52, 26 October 2005; Stevenj (Talk | contribs)
(diff) ←Older revision | Current revision | Newer revision→ (diff)

In this page, we'll go through a couple of simple examples that illustrate the process of computing fields, transmission/reflection spectra, and resonant modes in Meep. Most of the examples here will be two-dimensinal calculations, simply because they are quicker than 3d computations and they illustrate all of the essential features.

This tutorial uses the libctl/Scheme scripting interface to Meep, which is what we expect most users to employ most of the time. There is also a C++ interface that may give additional flexibility in some situations; that is described in the C++ tutorial.

In order to convert the HDF5 output files of Meep into images of the fields and so on, this tutorial uses our free h5utils programs. (You could also use any other program, such as Matlab, that supports reading HDF5 files.)

## The ctl file

The use of Meep revolves around the control file, abbreviated "ctl" and typically called something like foo.ctl (although you can use any file name you wish). The ctl file specifies the geometry you wish to study, the current sources, the outputs computed, and everything else specific to your calculation. Rather than a flat, inflexible file format, however, the ctl file is actually written in a scripting language. This means that it can be everything from a simple sequence of commands setting the geometry, etcetera, to a full-fledged program with user input, loops, and anything else that you might need.

Don't worry, though—simple things are simple (you don't need to be a Real Programmer), and even there you will appreciate the flexibility that a scripting language gives you. (e.g. you can input things in any order, without regard for whitespace, insert comments where you please, omit things when reasonable defaults are available...)

The ctl file is actually implemented on top of the libctl library, a set of utilities that are in turn built on top of the Scheme language. Thus, there are three sources of possible commands and syntax for a ctl file:

• Scheme, a powerful and beautiful programming language developed at MIT, which has a particularly simple syntax: all statements are of the form (function arguments...). We run Scheme under the GNU Guile interpreter (designed to be plugged into programs as a scripting and extension language). You don't need to know much Scheme for a basic ctl file, but it is always there if you need it; you can learn more about it from these Guile and Scheme links.
• libctl, a library that we built on top of Guile to simplify communication between Scheme and scientific computation software. libctl sets the basic tone of the interface and defines a number of useful functions (such as multi-variable optimization, numeric integration, and so on). See the libctl manual pages.
• Meep itself, which defines all the interface features that are specific to FDTD calculations. This manual is primarily focused on documenting these features.

Okay, let's continue with our tutorial. The Meep program is normally invoked by running something like:

unix% meep foo.ctl >& foo.out


which reads the ctl file foo.ctl and executes it, saving the output to the file foo.out. However, if you invoke meep with no arguments, you are dropped into an interactive mode in which you can type commands and see their results immediately. If you do that now, you can paste in the commands from the tutorial as you follow it and see what they do.

## Fields in a waveguide

For our first example, let's examine the field pattern excited by a localized CW source in a waveguide— first straight, then bent. Our waveguide will have (non-dispersive) $\varepsilon=12$ and width 1. That is, we pick units of length so that the width is 1, and define everything in terms of that (see also units in meep).

Before we define the structure, however, we have to define the computational cell. We're going to put a source at one end and watch it propagate down the waveguide in the x direction, so let's use a cell of length 15 in the x direction to give it some distance to propagate. In the y direction, we just need enough room so that the boundaries (below) don't affect the waveguide mode; let's give it a size of 8. We now specify these sizes in our ctl file via the geometry-lattice variable:

(set! geometry-lattice (make lattice (size 15 8 no-size)))


(The name geometry-lattice comes from MPB, where it can be used to define a more general periodic lattice. Although Meep supports periodic structures, it is less general than MPB in that affine grids are not supported.) set! is a Scheme command to set the value of an input variable. The last no-size parameter says that the computational cell has no size in the z direction, i.e. it is two-dimensional.

Now, we can add the waveguide. Most commonly, the structure is specified by a list of geometric objects, stored in the geometry variable. Here, we do:

(set! geometry (list
(make block (center 0 0) (size infinity 1 infinity)
(material (make dielectric (epsilon 12))))))


The waveguide is specified by a block (parallelepiped) of size \infty \times 1 \times \infty, with ε=12, centered at (0,0) (the center of the computational cell). By default, any place where there are no objects there is air (ε=1), although this can be changed by setting the default-material variable. The resulting structure is shown at right.

Dielectric function (black = high, white = air), for straight waveguide simulation.

Now that we have the structure, we need to specify the current sources, which is specified as a list called sources of source objects. The simplest thing is to add a point source Jz:

(set! sources (list
(make source
(src (make continuous-src (frequency 0.15)))
(component Ez)
(center -7 0))))


Here, we gave the source a frequency of 0.15, and specified a continuous-src which is just a fixed-frequency sinusoid exp( − iωt) that (by default) is turned on at t = 0. Recall that, in Meep units, frequency is specified in units of c, which is equivalent to the inverse of vacuum wavelength. Thus, 0.15 corresponds to a vacuum wavelength of about 6.67, or a wavelength of about 2 in the \epsilon=12 material—thus, our waveguide is half a wavelength wide, making it single-mode. Note also that to specify a Jz, we specify a component Ez (e.g. if we wanted a magnetic current, we would specify Hx, Hy, or Hz). The current is located at ( − 7,0), which is 1 unit to the right of the left edge of the cell—we always want to leave a little space between sources and the cell boundaries, to keep the boundary conditions from interfering with them.

Speaking of boundary conditions, we want to add absorbing boundaries around our cell. Absorbing boundaries in Meep are handled by perfectly matched layers (PML)— which aren't really a boundary condition at all, but rather a fictitious absorbing material added around the edges of the cell. To add an absorbing layer of thickness 1 around all sides of the cell, we do:

(set! pml-layers (list (make pml (thickness 1.0))))


pml-layers is a list of pml objects—you may have more than one pml object if you want PML layers only on certain sides of the cell, e.g. (make pml (thickness 1.0) (direction X) (side High)) specifies a PML layer on only the + x side. Now, make an important point: the PML layer is inside the cell, overlapping whatever objects you have there. So, in this case our PML overlaps our waveguide, which is what we want so that it will properly absorb waveguide modes. The finite thickness of the PML is important to reduce numerical reflections; see perfectly matched layers for more information.

Meep will discretize this structure in space and time, and that is specified by a single variable, resolution, that gives the number of pixels per distance unit. We'll set this resolution to 10, which corresponds to around 67 pixels/wavelength, or around 20 pixels/wavelength in the high-dielectric material. (n general, at least 8 pixels/wavelength in the highest dielectric is a good idea.) This will give us a $150\times80$ cell.

(set! resolution 10)


Now, we are ready to run the simulation! We do this by calling the run-until function. The first argument to run-until is the time to run for, and the subsequent arguments specify fields to output (or other kinds of analyses at each time step):

(run-until 200
(at-beginning output-epsilon)
(at-end output-efield-z))


Here, we are outputting the dielectric function ε and the electric-field component Ez, but have wrapped the output functions (which would otherwise run at every time step) in at-beginning and at-end, which do just what they say. There are several other such functions to modify the output behavior—and you can, of course, write your own, and in fact you can do any computation or output you want at any time during the time evolution (and even modify the simulation while it is running).

It should complete in a few seconds. If you are running interactively, the two output files will be called eps-000000.00.h5 and ez-000200.00.h5 (notice that the file names include the time at which they were output). If we were running a tutorial.ctl file, then the outputs will be tutorial-eps-000000.00.h5 and tutorial-ez-000200.00.h5. In any case, we can now analyze and visualize these files with a wide variety of programs that support the HDF5 format, including our own h5utils, and in particular the h5topng program to convert them to PNG images.

unix% h5topng -S3 eps-000000.00.h5


This will create eps-000000.00.png, where the -S3 increases the image scale by 3 (so that it is around 450 pixels wide, in this case).

## emacs and ctl

It is useful to have emacs use its scheme-mode for editing ctl files, so that hitting tab indents nicely, and so on. emacs does this automatically for files ending with ".scm"; to do it for files ending with ".ctl" as well, add the following lines to your ~/.emacs file:

(push '("\\.ctl\\'" . scheme-mode) auto-mode-alist)


or if your emacs version is 24.3 or earlier and you have other ".ctl" files which are not Scheme:

(if (assoc "\\.ctl" auto-mode-alist)
nil

(Incidentally, emacs scripts are written in "elisp," a language closely related to Scheme.)