diff --git a/Makefile b/Makefile index 50aa206..80c0aa0 100644 --- a/Makefile +++ b/Makefile @@ -137,7 +137,7 @@ S4r_LIBOBJS = \ $(OBJDIR)/S4r/periodic_off2.o ifndef LAPACK_LIB - S4_LIBOBJS += $(OBJDIR)/Eigensystems.o + S4_LIBOBJS += $(OBJDIR)/S4k/Eigensystems.o endif $(S4_LIBNAME): objdir $(S4_LIBOBJS) @@ -228,7 +228,7 @@ $(OBJDIR)/S4r/predicates.o: S4r/predicates.c #### Lua Frontend -$(OBJDIR)/S4k/main_lua.o: S4/main_lua.c +$(OBJDIR)/S4k/main_lua.o: S4/main_lua.c objdir $(CC) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ S4lua: $(OBJDIR)/S4k/main_lua.o $(S4_LIBNAME) $(CXX) $(CFLAGS) $(CPPFLAGS) $< -o $(S4_BINNAME) $(S4_LIBNAME) $(LIBS) $(LUA_LIB) @@ -239,12 +239,12 @@ $(OBJDIR)/S4r/lua_named_arg.o: S4r/lua_named_arg.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ $(OBJDIR)/S4r/S4r.o: S4r/S4r.cpp $(CXX) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ -S4rlua: $(OBJDIR)/S4r/main_lua.o $(OBJDIR)/S4r/lua_named_arg.o $(OBJDIR)/S4r/S4r.o $(S4r_LIBNAME) +S4rlua: objdir $(OBJDIR)/S4r/main_lua.o $(OBJDIR)/S4r/lua_named_arg.o $(OBJDIR)/S4r/S4r.o $(S4r_LIBNAME) $(CXX) $(CFLAGS) $(CPPFLAGS) $(OBJDIR)/S4r/main_lua.o $(OBJDIR)/S4r/lua_named_arg.o $(OBJDIR)/S4r/S4r.o -o $@ $(S4r_LIBNAME) $(LIBS) $(LUA_LIB) #### Python extension -S4_pyext: +S4_pyext: objdir $(S4_LIBNAME) echo "$(LIBS)" > $(OBJDIR)/tmp.txt sh gensetup.py.sh $(OBJDIR) $(S4_LIBNAME) python setup.py build diff --git a/Makefile.mingw32 b/Makefile.mingw32 new file mode 100644 index 0000000..e1727c2 --- /dev/null +++ b/Makefile.mingw32 @@ -0,0 +1,253 @@ +# To build: +# make +# Use the 'lib' target first to build the library, then either the Lua +# or Python targets are 'S4lua' and 'python_ext', respectively. + +# Set these to the flags needed to link against BLAS and Lapack. +# If left blank, then performance may be very poor. +# On Mac OS, +# BLAS_LIB = -framework vecLib +# LAPACK_LIB = -framework vecLib +# On Debian, with reference BLAS and Lapack (slow) +# BLAS_LIB = -lblas +# LAPACK_LIB = -llapack +BLAS_LIB = +LAPACK_LIB = + +# Specify the flags for Lua headers and libraries (only needed for Lua frontend) +# On Debian, +# LUA_INC = -I/usr/include/lua5.2 +# LUA_LIB = -llua5.2 -ldl -lm +LUA_INC = -I/c/code/libs/lua-5.2.3/install/include +LUA_LIB = -L/c/code/libs/lua-5.2.3/install/lib -llua -lm + +# Typically if installed, +# FFTW3_INC can be left empty +# FFTW3_LIB = -lfftw3 +FFTW3_INC = +FFTW3_LIB = + +# Typically, +# PTHREAD_INC = -DHAVE_UNISTD_H -lpthread +# PTHREAD_LIB = -lpthread +PTHREAD_INC = +PTHREAD_LIB = + +# Typically if installed, +# CHOLMOD_INC = -I/usr/include/suitesparse +# CHOLMOD_LIB = -lcholmod -lamd -lcolamd -lcamd -lccolamd +CHOLMOD_INC = +CHOLMOD_LIB = + +# Specify the MPI library +MPI_INC = +MPI_LIB = + +# Specify custom compilers if needed +CXX = g++ +CC = gcc + +CFLAGS = -O3 -msse -msse2 -msse3 -static + +OBJDIR = ./build +S4_BINNAME = $(OBJDIR)/S4 +S4_LIBNAME = $(OBJDIR)/libS4.a +S4r_LIBNAME = $(OBJDIR)/libS4r.a + +##################### DO NOT EDIT BELOW THIS LINE ##################### + +#### Set the compilation flags + +CPPFLAGS = -I. -IS4 -IS4/RNP -IS4/kiss_fft + +ifdef BLAS_LIB +CPPFLAGS += -DHAVE_BLAS +endif + +ifdef LAPACK_LIB +CPPFLAGS += -DHAVE_LAPACK +endif + +ifdef FFTW3_LIB +CPPFLAGS += -DHAVE_FFTW3 $(FFTW3_INC) +endif + +ifdef PTHREAD_LIB +CPPFLAGS += -DHAVE_LIBPTHREAD $(PTHREAD_INC) +endif + +ifdef CHOLMOD_LIB +CPPFLAGS += -DHAVE_LIBCHOLMOD $(CHOLMOD_INC) +endif + +ifdef MPI_LIB +CPPFLAGS += -DHAVE_MPI $(MPI_INC) +endif + +LIBS = $(BLAS_LIB) $(LAPACK_LIB) $(FFTW3_LIB) $(PTHREAD_LIB) $(CHOLMOD_LIB) + +#### Compilation targets + +all: $(S4_LIBNAME) + +objdir: + mkdir -p $(OBJDIR) + mkdir -p $(OBJDIR)/S4k + mkdir -p $(OBJDIR)/S4r + +S4_LIBOBJS = \ + $(OBJDIR)/S4k/S4.o \ + $(OBJDIR)/S4k/rcwa.o \ + $(OBJDIR)/S4k/fmm_common.o \ + $(OBJDIR)/S4k/fmm_FFT.o \ + $(OBJDIR)/S4k/fmm_kottke.o \ + $(OBJDIR)/S4k/fmm_closed.o \ + $(OBJDIR)/S4k/fmm_PolBasisNV.o \ + $(OBJDIR)/S4k/fmm_PolBasisVL.o \ + $(OBJDIR)/S4k/fmm_PolBasisJones.o \ + $(OBJDIR)/S4k/fmm_experimental.o \ + $(OBJDIR)/S4k/fft_iface.o \ + $(OBJDIR)/S4k/pattern.o \ + $(OBJDIR)/S4k/intersection.o \ + $(OBJDIR)/S4k/predicates.o \ + $(OBJDIR)/S4k/numalloc.o \ + $(OBJDIR)/S4k/gsel.o \ + $(OBJDIR)/S4k/sort.o \ + $(OBJDIR)/S4k/kiss_fft.o \ + $(OBJDIR)/S4k/kiss_fftnd.o \ + $(OBJDIR)/S4k/SpectrumSampler.o \ + $(OBJDIR)/S4k/cubature.o \ + $(OBJDIR)/S4k/Interpolator.o \ + $(OBJDIR)/S4k/convert.o + +S4r_LIBOBJS = \ + $(OBJDIR)/S4r/Material.o \ + $(OBJDIR)/S4r/LatticeGridRect.o \ + $(OBJDIR)/S4r/LatticeGridArb.o \ + $(OBJDIR)/S4r/POFF2Mesh.o \ + $(OBJDIR)/S4r/PeriodicMesh.o \ + $(OBJDIR)/S4r/Shape.o \ + $(OBJDIR)/S4r/Simulation.o \ + $(OBJDIR)/S4r/Layer.o \ + $(OBJDIR)/S4r/Pseudoinverse.o \ + $(OBJDIR)/S4r/Eigensystems.o \ + $(OBJDIR)/S4r/IRA.o \ + $(OBJDIR)/S4r/intersection.o \ + $(OBJDIR)/S4r/predicates.o \ + $(OBJDIR)/S4r/periodic_off2.o + +ifndef LAPACK_LIB + S4_LIBOBJS += $(OBJDIR)/S4k/Eigensystems.o +endif + +$(S4_LIBNAME): objdir $(S4_LIBOBJS) + $(AR) crvs $@ $(S4_LIBOBJS) +$(S4r_LIBNAME): objdir $(S4r_LIBOBJS) + $(AR) crvs $@ $(S4r_LIBOBJS) + +$(OBJDIR)/S4k/S4.o: S4/S4.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/rcwa.o: S4/rcwa.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_common.o: S4/fmm/fmm_common.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_FFT.o: S4/fmm/fmm_FFT.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_kottke.o: S4/fmm/fmm_kottke.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_closed.o: S4/fmm/fmm_closed.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_PolBasisNV.o: S4/fmm/fmm_PolBasisNV.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_PolBasisVL.o: S4/fmm/fmm_PolBasisVL.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_PolBasisJones.o: S4/fmm/fmm_PolBasisJones.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_experimental.o: S4/fmm/fmm_experimental.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fft_iface.o: S4/fmm/fft_iface.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/pattern.o: S4/pattern/pattern.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/intersection.o: S4/pattern/intersection.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/predicates.o: S4/pattern/predicates.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/numalloc.o: S4/numalloc.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/gsel.o: S4/gsel.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/sort.o: S4/sort.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/kiss_fft.o: S4/kiss_fft/kiss_fft.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/kiss_fftnd.o: S4/kiss_fft/tools/kiss_fftnd.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/SpectrumSampler.o: S4/SpectrumSampler.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/cubature.o: S4/cubature.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/Interpolator.o: S4/Interpolator.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/convert.o: S4/convert.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/Eigensystems.o: S4/RNP/Eigensystems.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + + + + +$(OBJDIR)/S4r/Material.o: S4r/Material.cpp S4r/Material.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/LatticeGridRect.o: S4r/LatticeGridRect.cpp S4r/PeriodicMesh.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/LatticeGridArb.o: S4r/LatticeGridArb.cpp S4r/PeriodicMesh.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/POFF2Mesh.o: S4r/POFF2Mesh.cpp S4r/PeriodicMesh.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/PeriodicMesh.o: S4r/PeriodicMesh.cpp S4r/PeriodicMesh.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Shape.o: S4r/Shape.cpp S4r/Shape.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Simulation.o: S4r/Simulation.cpp S4r/Simulation.hpp S4r/StarProduct.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Layer.o: S4r/Layer.cpp S4r/Layer.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Pseudoinverse.o: S4r/Pseudoinverse.cpp S4r/Pseudoinverse.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Eigensystems.o: S4r/Eigensystems.cpp S4r/Eigensystems.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/IRA.o: S4r/IRA.cpp S4r/IRA.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/intersection.o: S4r/intersection.c S4r/intersection.h + $(CC) -c -O3 $< -o $@ +$(OBJDIR)/S4r/periodic_off2.o: S4r/periodic_off2.c S4r/periodic_off2.h + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4r/predicates.o: S4r/predicates.c + $(CC) -c -O3 $< -o $@ + +#### Lua Frontend + +$(OBJDIR)/S4k/main_lua.o: S4/main_lua.c objdir + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ +S4lua: $(OBJDIR)/S4k/main_lua.o $(S4_LIBNAME) + $(CXX) $(CFLAGS) $(CPPFLAGS) $< -o $(S4_BINNAME) $(S4_LIBNAME) $(LIBS) $(LUA_LIB) + +$(OBJDIR)/S4r/main_lua.o: S4r/main_lua.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ +$(OBJDIR)/S4r/lua_named_arg.o: S4r/lua_named_arg.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ +$(OBJDIR)/S4r/S4r.o: S4r/S4r.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ +S4rlua: objdir $(OBJDIR)/S4r/main_lua.o $(OBJDIR)/S4r/lua_named_arg.o $(OBJDIR)/S4r/S4r.o $(S4r_LIBNAME) + $(CXX) $(CFLAGS) $(CPPFLAGS) $(OBJDIR)/S4r/main_lua.o $(OBJDIR)/S4r/lua_named_arg.o $(OBJDIR)/S4r/S4r.o -o $@ $(S4r_LIBNAME) $(LIBS) $(LUA_LIB) + +#### Python extension + +S4_pyext: objdir $(S4_LIBNAME) + echo "$(LIBS)" > $(OBJDIR)/tmp.txt + sh gensetup.py.sh $(OBJDIR) $(S4_LIBNAME) + python setup.py build + +clean: + rm -rf $(OBJDIR) diff --git a/Makefile.osx b/Makefile.osx new file mode 100644 index 0000000..69817e2 --- /dev/null +++ b/Makefile.osx @@ -0,0 +1,253 @@ +# To build: +# make +# Use the 'lib' target first to build the library, then either the Lua +# or Python targets are 'S4lua' and 'python_ext', respectively. + +# Set these to the flags needed to link against BLAS and Lapack. +# If left blank, then performance may be very poor. +# On Mac OS, +# BLAS_LIB = -framework vecLib +# LAPACK_LIB = -framework vecLib +# On Debian, with reference BLAS and Lapack (slow) +# BLAS_LIB = -lblas +# LAPACK_LIB = -llapack +BLAS_LIB = -framework vecLib +LAPACK_LIB = -framework vecLib + +# Specify the flags for Lua headers and libraries (only needed for Lua frontend) +# On Debian, +# LUA_INC = -I/usr/include/lua5.2 +# LUA_LIB = -llua5.2 -ldl -lm +LUA_INC = -Ilua-5.2.3/install/include +LUA_LIB = -Llua-5.2.3/install/lib -llua -lm + +# Typically if installed, +# FFTW3_INC can be left empty +# FFTW3_LIB = -lfftw3 +FFTW3_INC = +FFTW3_LIB = + +# Typically, +# PTHREAD_INC = -DHAVE_UNISTD_H -lpthread +# PTHREAD_LIB = -lpthread +PTHREAD_INC = +PTHREAD_LIB = + +# Typically if installed, +# CHOLMOD_INC = -I/usr/include/suitesparse +# CHOLMOD_LIB = -lcholmod -lamd -lcolamd -lcamd -lccolamd +CHOLMOD_INC = +CHOLMOD_LIB = + +# Specify the MPI library +MPI_INC = +MPI_LIB = + +# Specify custom compilers if needed +CXX = g++ +CC = gcc + +CFLAGS = -O3 -fPIC + +OBJDIR = ./build +S4_BINNAME = $(OBJDIR)/S4 +S4_LIBNAME = $(OBJDIR)/libS4.a +S4r_LIBNAME = $(OBJDIR)/libS4r.a + +##################### DO NOT EDIT BELOW THIS LINE ##################### + +#### Set the compilation flags + +CPPFLAGS = -I. -IS4 -IS4/RNP -IS4/kiss_fft + +ifdef BLAS_LIB +CPPFLAGS += -DHAVE_BLAS +endif + +ifdef LAPACK_LIB +CPPFLAGS += -DHAVE_LAPACK +endif + +ifdef FFTW3_LIB +CPPFLAGS += -DHAVE_FFTW3 $(FFTW3_INC) +endif + +ifdef PTHREAD_LIB +CPPFLAGS += -DHAVE_LIBPTHREAD $(PTHREAD_INC) +endif + +ifdef CHOLMOD_LIB +CPPFLAGS += -DHAVE_LIBCHOLMOD $(CHOLMOD_INC) +endif + +ifdef MPI_LIB +CPPFLAGS += -DHAVE_MPI $(MPI_INC) +endif + +LIBS = $(BLAS_LIB) $(LAPACK_LIB) $(FFTW3_LIB) $(PTHREAD_LIB) $(CHOLMOD_LIB) + +#### Compilation targets + +all: $(S4_LIBNAME) + +objdir: + mkdir -p $(OBJDIR) + mkdir -p $(OBJDIR)/S4k + mkdir -p $(OBJDIR)/S4r + +S4_LIBOBJS = \ + $(OBJDIR)/S4k/S4.o \ + $(OBJDIR)/S4k/rcwa.o \ + $(OBJDIR)/S4k/fmm_common.o \ + $(OBJDIR)/S4k/fmm_FFT.o \ + $(OBJDIR)/S4k/fmm_kottke.o \ + $(OBJDIR)/S4k/fmm_closed.o \ + $(OBJDIR)/S4k/fmm_PolBasisNV.o \ + $(OBJDIR)/S4k/fmm_PolBasisVL.o \ + $(OBJDIR)/S4k/fmm_PolBasisJones.o \ + $(OBJDIR)/S4k/fmm_experimental.o \ + $(OBJDIR)/S4k/fft_iface.o \ + $(OBJDIR)/S4k/pattern.o \ + $(OBJDIR)/S4k/intersection.o \ + $(OBJDIR)/S4k/predicates.o \ + $(OBJDIR)/S4k/numalloc.o \ + $(OBJDIR)/S4k/gsel.o \ + $(OBJDIR)/S4k/sort.o \ + $(OBJDIR)/S4k/kiss_fft.o \ + $(OBJDIR)/S4k/kiss_fftnd.o \ + $(OBJDIR)/S4k/SpectrumSampler.o \ + $(OBJDIR)/S4k/cubature.o \ + $(OBJDIR)/S4k/Interpolator.o \ + $(OBJDIR)/S4k/convert.o + +S4r_LIBOBJS = \ + $(OBJDIR)/S4r/Material.o \ + $(OBJDIR)/S4r/LatticeGridRect.o \ + $(OBJDIR)/S4r/LatticeGridArb.o \ + $(OBJDIR)/S4r/POFF2Mesh.o \ + $(OBJDIR)/S4r/PeriodicMesh.o \ + $(OBJDIR)/S4r/Shape.o \ + $(OBJDIR)/S4r/Simulation.o \ + $(OBJDIR)/S4r/Layer.o \ + $(OBJDIR)/S4r/Pseudoinverse.o \ + $(OBJDIR)/S4r/Eigensystems.o \ + $(OBJDIR)/S4r/IRA.o \ + $(OBJDIR)/S4r/intersection.o \ + $(OBJDIR)/S4r/predicates.o \ + $(OBJDIR)/S4r/periodic_off2.o + +ifndef LAPACK_LIB + S4_LIBOBJS += $(OBJDIR)/S4k/Eigensystems.o +endif + +$(S4_LIBNAME): objdir $(S4_LIBOBJS) + $(AR) crvs $@ $(S4_LIBOBJS) +$(S4r_LIBNAME): objdir $(S4r_LIBOBJS) + $(AR) crvs $@ $(S4r_LIBOBJS) + +$(OBJDIR)/S4k/S4.o: S4/S4.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/rcwa.o: S4/rcwa.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_common.o: S4/fmm/fmm_common.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_FFT.o: S4/fmm/fmm_FFT.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_kottke.o: S4/fmm/fmm_kottke.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_closed.o: S4/fmm/fmm_closed.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_PolBasisNV.o: S4/fmm/fmm_PolBasisNV.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_PolBasisVL.o: S4/fmm/fmm_PolBasisVL.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_PolBasisJones.o: S4/fmm/fmm_PolBasisJones.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fmm_experimental.o: S4/fmm/fmm_experimental.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/fft_iface.o: S4/fmm/fft_iface.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/pattern.o: S4/pattern/pattern.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/intersection.o: S4/pattern/intersection.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/predicates.o: S4/pattern/predicates.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/numalloc.o: S4/numalloc.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/gsel.o: S4/gsel.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/sort.o: S4/sort.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/kiss_fft.o: S4/kiss_fft/kiss_fft.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/kiss_fftnd.o: S4/kiss_fft/tools/kiss_fftnd.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/SpectrumSampler.o: S4/SpectrumSampler.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/cubature.o: S4/cubature.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/Interpolator.o: S4/Interpolator.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/convert.o: S4/convert.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4k/Eigensystems.o: S4/RNP/Eigensystems.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + + + + +$(OBJDIR)/S4r/Material.o: S4r/Material.cpp S4r/Material.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/LatticeGridRect.o: S4r/LatticeGridRect.cpp S4r/PeriodicMesh.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/LatticeGridArb.o: S4r/LatticeGridArb.cpp S4r/PeriodicMesh.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/POFF2Mesh.o: S4r/POFF2Mesh.cpp S4r/PeriodicMesh.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/PeriodicMesh.o: S4r/PeriodicMesh.cpp S4r/PeriodicMesh.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Shape.o: S4r/Shape.cpp S4r/Shape.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Simulation.o: S4r/Simulation.cpp S4r/Simulation.hpp S4r/StarProduct.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Layer.o: S4r/Layer.cpp S4r/Layer.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Pseudoinverse.o: S4r/Pseudoinverse.cpp S4r/Pseudoinverse.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/Eigensystems.o: S4r/Eigensystems.cpp S4r/Eigensystems.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/IRA.o: S4r/IRA.cpp S4r/IRA.hpp S4r/Types.hpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -I. $< -o $@ +$(OBJDIR)/S4r/intersection.o: S4r/intersection.c S4r/intersection.h + $(CC) -c -O3 $< -o $@ +$(OBJDIR)/S4r/periodic_off2.o: S4r/periodic_off2.c S4r/periodic_off2.h + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +$(OBJDIR)/S4r/predicates.o: S4r/predicates.c + $(CC) -c -O3 $< -o $@ + +#### Lua Frontend + +$(OBJDIR)/S4k/main_lua.o: S4/main_lua.c objdir + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ +S4lua: $(OBJDIR)/S4k/main_lua.o $(S4_LIBNAME) + $(CXX) $(CFLAGS) $(CPPFLAGS) $< -o $(S4_BINNAME) $(S4_LIBNAME) $(LIBS) $(LUA_LIB) + +$(OBJDIR)/S4r/main_lua.o: S4r/main_lua.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ +$(OBJDIR)/S4r/lua_named_arg.o: S4r/lua_named_arg.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ +$(OBJDIR)/S4r/S4r.o: S4r/S4r.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) $(LUA_INC) $< -o $@ +S4rlua: objdir $(OBJDIR)/S4r/main_lua.o $(OBJDIR)/S4r/lua_named_arg.o $(OBJDIR)/S4r/S4r.o $(S4r_LIBNAME) + $(CXX) $(CFLAGS) $(CPPFLAGS) $(OBJDIR)/S4r/main_lua.o $(OBJDIR)/S4r/lua_named_arg.o $(OBJDIR)/S4r/S4r.o -o $@ $(S4r_LIBNAME) $(LIBS) $(LUA_LIB) + +#### Python extension + +S4_pyext: objdir $(S4_LIBNAME) + echo "$(LIBS)" > $(OBJDIR)/tmp.txt + sh gensetup.py.sh $(OBJDIR) $(S4_LIBNAME) + python setup.py build + +clean: + rm -rf $(OBJDIR) diff --git a/S4/config.h b/S4/config.h new file mode 100644 index 0000000..a84dbec --- /dev/null +++ b/S4/config.h @@ -0,0 +1,10 @@ +#define F77_FUNC(l,u) l##_ + +#define PACKAGE "S4" +#define PACKAGE_BUGREPORT "vkl@stanford.edu" +#define PACKAGE_NAME "S4" +#define PACKAGE_STRING "S4 1.1.0" +#define PACKAGE_TARNAME "S4" +#define PACKAGE_URL "" +#define PACKAGE_VERSION "1.1.0" +#define VERSION "1.1.0" diff --git a/doc/build/html/.buildinfo b/doc/build/html/.buildinfo new file mode 100644 index 0000000..b63fdc6 --- /dev/null +++ b/doc/build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 618bb5697c0274d0531b38c39e4df8ea +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/doc/build/html/_images/schem_640.png b/doc/build/html/_images/schem_640.png new file mode 100644 index 0000000..3415e2b Binary files /dev/null and b/doc/build/html/_images/schem_640.png differ diff --git a/doc/build/html/_images/spec.png b/doc/build/html/_images/spec.png new file mode 100644 index 0000000..8976880 Binary files /dev/null and b/doc/build/html/_images/spec.png differ diff --git a/doc/build/html/_sources/changelog.txt b/doc/build/html/_sources/changelog.txt new file mode 100644 index 0000000..379589b --- /dev/null +++ b/doc/build/html/_sources/changelog.txt @@ -0,0 +1,87 @@ +Changelog +========= + +2013-12-31 + Added new Python extension frontend. +2013-12-26 + Added ability to efficiently output fields on a regular grid of points using an FFT. +2013-12-25 + Fixed incorrect output of z-components of E-fields (incorrect application Epsilon_inv). +2013-10-31 + Added optional order parameter to SetExcitationPlanewave. +2013-10-16 + Layer integrals now also return imaginary parts. +2013-08-15 + Fixed bug with SetLatticeTruncation not having an effect. +2013-05-29 + Added additional options to Lanczos smoothing. Upgraded support to Lua 5.2 (dropped support for 5.1). +2013-03-30 + Added GetLayerZIntegral to return line integrals (thanks to Ken Wang for the feature request). Changed the return convention for GetAmplitudes, and added documentation for both functions. +2013-03-21 + Added GetAmplitudes to return the raw amplitudes for phase retrieval (thanks to Olivier Gauthier-Lafaye for the feature request). +2013-02-19 + pattern.c now detects 1D patterns and special cases them. Eigensolver performs workspace query for greater efficiency, and Fortran interfaces tidied up. Lanczos smoothing is now an option in FFT and PolBasisVL. Added SetLayerThickness to change only thickness and not affect the cached eigenmodes. +2011-11-21 + Fixed bug with rotation and translation in OutputPatternDescription (thanks Aaswath). +2011-09-16 + Eigenvector basis for uniform layers not stored (identity matrix). Added option UseLessMemory to not store kp (k-cross) matrices. +2011-09-06 + Fixed minor bugs and passes Valgrind without problems (for a few test runs). +2011-08-31 + Added GetDiffractionOrder(). +2011-08-30 + Fixed normal-vector bug, resolving convergence issues with subpixel-smoothing and rectangular shapes. +2011-08-25 + Added CHOLMOD direct solver to pattern.c. +2011-08-23 + Fixed segment-segment intersection code. Several cases of incorrect dielectric discretization have been fixed. + Changed Enable/Disable* functions to Use*. +2011-06-20 + Added MPI support. Compile with HAVE_MPI. S4.MPIRank and MPISize are available regardless of MPI support. +2011-04-22 + Halved the Lanczos filter spatial width. This seems to improve convergence. + Changed default resolution to 8 from 64. +2011-04-21 + Added Kottke's subpixel smoothing method. Disabled by default. + SetLattice can now take a single number for 1D periodicity. + SpectrumSampler can now be parallelized. +2011-04-20 + Changed PolarizationBasisOversamplingFactor to Resolution. +2011-04-18 + Fixed crash when using Kiss FFT. I overzealously converted free to S4_free for kiss_fft. +2011-03-27 + Switched numerical memory allocation to 16-byte alignment. LinearSolve's now use LAPACK blocked code. Fixed some memory leaks with S4_Simulation objects (field cache was not being freed). +2011-03-20 + Added Integrate function. +2010-10-28 + Fixed nan output due to uninitialized matrices Ml, Mlp1, Bl, Blp1 in rcwa.cpp. +2010-09-10 + Fixed incorrect output of z-components of E- and H-fields (missing in-plane k-vector dependent phase). +2010-08-23 + Fixed memory leak in S4_DestroySolution; kx and Bands and Solution structures were not freed. +2010-08-10 + Fixed erroneous generation of values for Fourier transform for non-tensor materials in the context of a with-tensor stack. + Added S4.ConvertUnits. +2010-08-09 + Fixed a bug with S-Matrix generation between two identical layers (previous results were incorrect). +2010-08-05 + Added anisotropic material support (currently incompatible with polarization basis, but without warning). Added cubic hermite spline interpolation. +2010-08-04 + Added real material data for metals. +2010-08-03 + Traced a problem with incorrect multithreaded results back to LAPACK. It is critical that LAPACK not use static allocation for local arrays (fixed with `-frecursive`). +2010-07-29 + Fixed 1D lattice G selection (even numbers would cause duplicates) +2010-07-28 + Fixed planewave excitation calculations for off-normal incidence. Previous s- and p-polarizations were mixed up and wrong. Added command line switches `a` and `t`. +2010-07-26 + Fixed circular truncation code; was dropping certain orders (2,2 on a square lattice). +2010-07-24 + Fixed polygon patterning (incorrect Fourier transform formulation). +2010-07-23 + Added ability to output diffraction efficiency, obtain the G-vector list, and fixed the Fourier transforms for non-unit area unit cells. +2010-07-22 + Added caching of polarization basis vector field Fourier transform matrices. + Repeated computation of the same structure at different frequencies or k-vectors is much faster now that the vector field does not need to be recreated each time. +2010-07-21 + Initial announcement of S4. Supports multithreading. diff --git a/doc/build/html/_sources/citing.txt b/doc/build/html/_sources/citing.txt new file mode 100644 index 0000000..e924a31 --- /dev/null +++ b/doc/build/html/_sources/citing.txt @@ -0,0 +1,32 @@ +How to cite +=========== + +We kindly ask that you reference the |S4| package and its authors in any publication for which you used it. +This is obviously neither legally binding nor enforceable, but we hope that you do. + +The preferred citation for |S4| is the following paper: + + Victor Liu and Shanhui Fan, "|S4|: A free electromagnetic solver for layered periodic structures," Computer Physics Communications **183**, 2233-2244 (2012) + `http://dx.doi.org/10.1016/j.cpc.2012.04.026 `_ + +Or, in BibTeX format:: + + @article{Liu20122233, + author = "Victor Liu and Shanhui Fan", + title = "S$^4$ : A free electromagnetic solver for layered periodic structures", + journal = "Computer Physics Communications", + volume = "183", + number = "10", + pages = "2233 - 2244", + year = "2012", + issn = "0010-4655", + doi = "10.1016/j.cpc.2012.04.026", + url = "http://www.sciencedirect.com/science/article/pii/S0010465512001658", + } + +It is not absolutely necessary for the "4" in |S4| to be a superscript, but it is more correct if it is. +A brief description of the algorithm might be: + + The transmission spectrum was computed using the Fourier Modal Method using a freely available software package [ref]. + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_sources/dev_info.txt b/doc/build/html/_sources/dev_info.txt new file mode 100644 index 0000000..2afb75f --- /dev/null +++ b/doc/build/html/_sources/dev_info.txt @@ -0,0 +1,95 @@ +Developer Info +============== + +Dependencies +------------ + +* Lua 5.2.x, both headers and libraries. +* Python 2 or 3, both headers and libraries. +* BLAS, or equivalent, library only. +* LAPACK (optional, 3.2 or later), library only. +* Pthreads (optional), both headers and libraries. +* FFTW3 (optional, 3.x), both headers and libraries. +* CHOLMOD (optional), both headers and libraries. + +BLAS +^^^^ + +The performance of |S4| is directly dependent on the performance of the BLAS library that it is linked against. Without a BLAS library, the default RNP routines are used, which are suboptimal. It is recommended that either vendor specific routines (Intel MKL or AMD AMCL) are used, or tuned libraries such as ATLAS or OpenBLAS are used. Vendor specific routines have incompatible calling/naming conventions than the standard Fortran interface, so some porting effort is required. Note that OpenBLAS should be compiled without threading if threading is enabled within |S4|; otherwise results may not be correct. Installing these packages from official distribution repositories is almost always a bad idea, since the code must be tuned to the particular machine it will run on. + +LAPACK +^^^^^^ + +If a precompiled LAPACK library is used, ensure ZGEEV is thread safe for large matrices. Specifically, `bug0061 `_ in the LAPACK errata means that the maximum stack space reserved by the Fortran compiler used to build LAPACK must be sufficient to hold certain temporaries on the stack instead of in static (shared) memory. The best way to avoid this with GFortran is to use the -frecursive flag. A simple test of thread safety is provided in the ``testing/Lapackthreadtest/`` directory. + +If no LAPACK library is available, the default RNP routines are used, which are suboptimal due to lack of blocked routines. However, they are definitely thread-safe. + +CHOLMOD +^^^^^^^ + +Although not required, it is recommended when polarization decomposition settings are enabled, since without it, a conjugate gradient solver is used instead. The conjugate gradient solver does not always converge for fine discretizations. + +FFTW +^^^^ + +This library is optional; the Kiss FFT library is used instead when FFTW is not present. When available the version must be 3.x. This does not have a great effect on simulation speed since the FFT is required only a handful of times, and tends to be rather small in problem size. + +Porting +------- + +The code is developed in Windows under MinGW+MSYS and runs primarily in UNIX-like environments. For other platforms, the following list details the main problem areas. + + In ``main.c`` near the top dealing with threads (this is not a problem if Pthreads are disabled). + In ``pattern/predicates.c``, the settings may need modification to enable robust computations. + In ``numalloc.c``, a more efficient aligned allocator may be supplied instead of the default. + +Program structure +----------------- + +|S4| is built as a library on top of the Lua programming language, or as a Python extension. + +|S4| has 3 main layers: + +``main_lua.c`` + Specifies the Lua interface, which passes arguments on to the S4 layer. +``S4.cpp`` + The glue between the user specified information and the RCWA specification. The heavy lifting here is mainly determining which Fourier orders to use, and generating the Fourier dielectric matrices. The header S4.h is C-compatible and allows binding of a custom interface to the internals, or use programmatically as a component. +``rcwa.cpp`` + The real RCWA and S-matrix algorithms are contained here. The main functions are solving the layer band structure, composing S-matrices for stacks of layers, and solving for solutions given input fields. Also contained within here are functions for manipulating solution vectors and computing various quantities of interest. + +Auxilliary functions +^^^^^^^^^^^^^^^^^^^^ + +``pattern.c/intersection.c`` + A self-contained library for representing layer patterning, as well as generating proper discretizations, Fourier transforms of the patterns, and quasiharmonic conformal flow fields. fmm + A set of different formulations to generate the Fourier components of the dielectric function. ``kiss_fft`` + A simple FFT library for performing numerical Fourier transforms of the conformal vector fields. ``RNP`` + A library of numerical linear algebra functions, and a thin layer over the BLAS and LAPACK libraries. +``SpectrumSampler``/``Interpolator`` + These are addtional convenience modules to perform commonly needed tasks. + +Areas of improvement +-------------------- + +* Symmetry detection. Hermitian or symmetric eigenproblems are not detected and specialized currently. +* Bandsolving. 3D layered structure bandsolving can be implemented relatively straightforwardly. +* Robustness and efficiency of G-vector selection. The current implementation is likely unnecessarily slow. Robustness of the algorithm for a very wide variety of lattices remains to be investigated. +* Conjugate Gradient implementation in `pattern.c`. The current CG implementation is a textbook implementation, with hard coded regularization. +* Workspace pre-allocation for repeated calls. Currently, many workspace parameters in `rcwa.cpp` are ignored, defaulting to automatic allocation. For repeated small calls, the allocation overhead may be substantial. Profiling is needed. +* A full programming API in `S4.h`. The current Lua interface reaches into the `Simulation` structure for certain functions. It is best to hide the details of the `Simulation` structure behind an opaque pointer and fix an API. +* Parallelization over layer band structure computations. For a large number of non-trivial layers, a rather simple parallelization would be to compute the bands of the layers in parallel. It is unclear whether this requires an invasive modification of S4.cpp. +* Parallelization over S-matrix assembly. The construction of the S-matrix should be parallelizable by a divide-and-conquer algorithm. Furthermore, it ought to be possible to cache intermediate results to speed up computing many S-matrices. +* Graceful handling of diffraction threshold frequencies. If a frequency happens to cause a zero eigenvalue in a layer's band structure, some internal matrices become singular, and no solution is obtainable. This requires a thorough theoretical investigation. + +Coding conventions +------------------ + +The code is mostly C-styled C++. The need to use C++ is mainly for the complex number type. There should never be non-trivial objects (only Plain Old Data structs), and certainly no inheritance, polymorphism, or templates (except in RNP). + +Indentation should be 4 spaces per tab. Always use tabs instead of spaces. The actual tab width should never matter for readability, meaning tabs can only exist contiguously starting from the left-most column, and comment blocks should never sit at the end of lines of code. Lines should be kept to around 72 or 80 characters in length if possible, especially for comment blocks. + +Functions generally are in Lapack-style, where there are a large number of well defined inputs, and a number of outputs returned by pointers. Functions return an integer code, with negative values corresponding to invalid parameters. When appropriate, workspaces can be passed in to reduce the number of dynamic allocations. Also, when convenient, workspace querying should be supported. + +The code should compile cleanly with all warnings enabled. The only exemptions are external libraries like Kiss FFT or the geometric predicates sources. + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_sources/faq.txt b/doc/build/html/_sources/faq.txt new file mode 100644 index 0000000..e5e524a --- /dev/null +++ b/doc/build/html/_sources/faq.txt @@ -0,0 +1,34 @@ +Frequently Asked Questions +========================== + +* Where is the unit cell located and do I need to define periodic copies of patterns? + + This a tricky topic. + If you use an FMM formuation which is based on analytic Fourier transforms (which includes the default settings), then all patterns are automatically periodized, and in some sense, the shape and location of the unit cell is irrelevant. + For spatially sampled FMM formulations (those that rely on an FFT), the unit cell is the Wigner-Seitz cell centered at the origin. + For these formulations you need to specify periodic copies. + You should always check that the patterning is specified correctly using ``GetEpsilon()`` or ``OutputLayerPatternRealization()``. + +* What happens if I try to compute a quantity "outside" the structure? + + For example, if you specify a negative z coordinate, that corresponds to being within the first layer, since it is assumed the first layer extends infinitely towards negative infinity in the z direction. + Similarly, if you specify a z coordinate past the total thickness of all layers, it is within the last layer. + This is why you can specify zero thickness for the first and last layers. + However, it is recommended that you increase the thickness of the first and last layers sufficiently so that you don't need to compute quantities "outside" the specified structure since field quantities may suffer from numerical instability in those cases. + +* How do I specify frequency dependent material parameters? + + If you have a loop iterating over frequencies, then within the loop simply set new epsilon values for the materials. + In order to incorporate values from tabulated data, you can use the Interpolator object and pass it a table of values. + Large tables can be defined in separate files and included using the Lua ``dofile()`` function. + +* Why is the POVRay output wrong? + + The POVRay feature is only to provide a starting point for writing an actual POVRay script. + It is not guaranteed to be correct. You should not rely on this feature. + +* Should the 4 in |S4| be superscripted in publications? + + Although we would prefer that it be superscripted, it does not have to be. The preferred way to typeset it in LaTeX is: S$^4$. + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_sources/index.txt b/doc/build/html/_sources/index.txt new file mode 100644 index 0000000..c15e5ef --- /dev/null +++ b/doc/build/html/_sources/index.txt @@ -0,0 +1,63 @@ +.. S4 documentation master file, created by + sphinx-quickstart on Tue Dec 31 12:59:38 2013. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Introduction to |S4| +==================== + +What is it? +----------- + +|S4| (or simply S4) stands for Stanford Stratified Structure Solver, a frequency domain code to solve the linear Maxwell's equations in layered periodic structures. +Internally, it uses Rigorous Coupled Wave Analysis (RCWA; also called the Fourier Modal Method (FMM)) and the S-matrix algorithm. +The program is implemented using a `Lua `_ frontend, or alternatively, as a `Python `_ extension. +|S4| was developed by `Victor Liu `_ of the `Fan Group `_ in the `Stanford Electrical Engineering Department `_. + +.. image:: schem_640.png + +What can it compute? +-------------------- + +|S4| can compute transmission, reflection, or absorption spectra of structures composed of periodic, patterned, planar layers. +The electromagnetic fields throughout the structure can also be obtained, as well as certain line and volume integrals. +The spectra obtained from |S4| are extremely smooth, making it easier for local and global optimization. + +.. image:: spec.* + +Documentation Contents +---------------------- + +.. toctree:: + :maxdepth: 2 + + install + tutorial + lua_api + python_api + units + faq + changelog + dev_info + license + citing + +Releases +-------- + +* Version 1.1 + + Latest version using Lua 5.2.x and supports Python. + +* Version 1.0 + + This is the original version that was published in Computer Physics Communications. It requires on Lua 5.1.x and packs Python bindings. + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_sources/install.txt b/doc/build/html/_sources/install.txt new file mode 100644 index 0000000..6a512d2 --- /dev/null +++ b/doc/build/html/_sources/install.txt @@ -0,0 +1,74 @@ +Download & Installation +======================= + +There are two choices for downloading |S4|: downloading a binary package from below, or cloning the GitHub respository and building from source. +The latter is the preferred method for obtaining the latest features and bug fixes. + +Binary packages +--------------- + +The binary packages do not contain the examples and documentation, and are compiled with the bare minimum of features. +You need to download that separately. + +* Version 1.1 + + * `Windows (32-bit) EXE `_ (Lua frontend) + * `Mac OS X (compiled on 10.8.5) `_ (Lua frontend) + * `Examples and documentation `_ + +* Version 1.0 (not recommended) + + * `Source with documentation and examples `_ + * `Windows EXE `_ + * `Mac OS X 10.6.8 `_ + +GitHub repository +----------------- + +The source code is located at this `GitHub repository `_. +You can clone it with the command:: + + git clone https://github.com/victorliu/S4.git + +Compiling from source +--------------------- + +Dependencies +^^^^^^^^^^^^ + +Before compiling, there are a number of packages that are recommended. +None of these is required except for either Lua or Python. + +* `Lua `_ 5.2.x - This is required for the Lua frontend. + Either this or Python is required. + On Ubuntu or Debian, the repository package is called ``liblua5.2-dev``. +* `Python `_ 2.x or 3.x - This is required to build |S4| as a Python extension. + Either this or Lua is required. + On Ubuntu or Debian, the repository package is called ``python-dev`` or ``python3-dev``. +* BLAS and Lapack implementation - Optional, but highly recommended. It is suggested that `OpenBLAS `_ be used. +* `FFTW3 `_ - Optional, provides a 2-3x speedup in FFT computations. + On Ubuntu or Debian, the repository package is called ``libfftw3-dev``. +* `CHOLMOD `_ - Optional, provides a speedup in certain FMM formulations. + On Ubuntu or Debian, install the repository package is called ``libsuitesparse-dev``. +* POSIX Threads - Optional, typically provided by the compiler. Allows multi-threading support on shared-memory machines. +* MPI - Optional, provides support for parallel computing on distributed-memory machines. + +Compilation +^^^^^^^^^^^^^^^^^^^^^^^^ + +# Edit Makefile.custom and set the library flags for all the dependencies that can be provided. +# Run:: + + make lib + +# Next, build either the Lua frontend:: + + make S4lua + + or the Python extension:: + + make S4_pyext + +# The resulting Lua binary is just called ``S4``, and the Python shared object is ``build/lib.*/S4.so``. + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_sources/license.txt b/doc/build/html/_sources/license.txt new file mode 100644 index 0000000..f32caab --- /dev/null +++ b/doc/build/html/_sources/license.txt @@ -0,0 +1,29 @@ +License and Copyright +===================== + +|S4| is copyright (c) 2009-2014, Stanford University. + +|S4| is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. You can also find it on the GNU web site: + +`http://www.gnu.org/copyleft/gpl.html `_ + +Specific components +------------------- + +The files ``cubature.c`` and ``cubature.h`` were taken from Stephen G. Johnson's `Cubature package `_. See the page for details. + +The files ``sort.c`` and ``sort.h`` were taken from Rusty Russell's modification of the original libc routines. See the `CCAN page `_ for details. + +The file ``predicates.c`` is public domain, written by Jonathan Richard Shewchuk. See the `Quake project page `_ for details. + +Distributed with |S4| is the `Kiss FFT library `_. It is copyright (c) 2003-2014 by Mark Borgerding. + +As a clarification, we should note that Lua script (.lua) files, written by the user (i.e. not containing code distributed with |S4|) and loaded at runtime by the |S4| software, are not considered derived works of |S4| and do not fall thereby under the restrictions of the GNU General Public License. + +In addition, all of the example Lua code in these pages, as well as the example Lua files in the ``examples/`` directory, may be freely used, modified, and redistributed, without any restrictions. (The warranty disclaimer still applies, of course.) + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_sources/lua_api.txt b/doc/build/html/_sources/lua_api.txt new file mode 100644 index 0000000..21d53db --- /dev/null +++ b/doc/build/html/_sources/lua_api.txt @@ -0,0 +1,1465 @@ +.. default-domain:: lua + +.. _lua-api-label: + +Lua API reference +================= + +|S4| is built as a set of extensions to the `Lua scripting language `_. +Usage of |S4| involves writing a Lua script to call into various parts of |S4|. +Here we describe all of the |S4| specific functions that can be called within the Lua environment. + +S4 library +---------- + +.. module:: S4 + +All top level functions of |S4| are located in the ``S4`` library. +These functions mainly return objects which can be manipulated to obtain desired results. + +.. function:: NewSimulation() + + Returns a new blank `Simulation object`_. + + Usage:: + + S = S4.NewSimulation() + + Arguments: + + None. + + Return values: + + S + A new `Simulation object`_. + +.. function:: NewSpectrumSampler(f_start, f_end, options) + + Returns a new `SpectrumSampler object`_. + + Usage:: + + sampler = S4.NewSpectrumSampler(f_start, f_end, options) + + Arguments: + + f_start, f_end + (number) Starting and ending frequencies of the frequency range in which to sample. + options + (table) A table of options controlling the sampling behavior. The keys and expected values are described below. If any option is not specified, the default value is used. Any out-of-range values are clamped to the valid range. + InitialNumPoints + (integer) The initial number of (uniformly spaced) sample points to use. If this value is not large enough, fine features may be missed. The default is 33. + RangeThreshold + (number) The threshold below which the difference between adjacent result values will not cause an interval to be subdivided. The default is 0.001. + MaxBend + (number) The cosine of the maximum bend angle of the normalized angle between adjacent segments. + For angles larger than the maximum bend angle, one of the adjacent intervals is subdivided. + The default bend angle is 10 degrees. + MinimumSpacing + (number) The relative frequency space (relative to the sampling interval size) below which subdivision will not occur. The default is 1e-6. + Parallelize + (boolean) Allows multiple frequency points to be solved in parallel. This option affects which methods can be called for a SpectrumSampler object. The default is false. + + Return values: + + sampler + A new `SpectrumSampler object`_. + +.. function:: NewInterpolator(type, table) + + Returns a new `Interpolator object`_. + + Usage:: + + interpolator = S4.NewInterpolator('type', { + {x1, {y1_1, y1_2, ... }}, + {x2, {y2_1, y2_2, ... }}, + ... + }) + + Arguments: + + type + (string) Type of interpolation to use. + + 'linear' + Performs linear interpolation (and extrapolation) between values. + 'cubic hermite spline' + Uses a cubic Hermite spline interpolation with Kochanek-Bartels tangents (really just a Catmull-Rom spline). + + table + The second argument should be a table of tables. + Each subtable should have as its first element the abscissa of a data sample, and the second element should be a table of all the ordinate values. + The ordinate ordering is clearly important, and only the number of ordinate values for the first abscissa value determines the assumed number of ordinate values for the remaining abscissae. + + Return values: + + interpolator + A new `Interpolator object`_. + +.. function:: SolveInParallel(layername, ...) + + Forces the computation of a layer solution for several simulation objects in parallel. + When compiled without thread support, the computations are done serially. + + Usage:: + + S4.SolveInParallel('layer', Sa, Sb, ...) + + Arguments: + + layer + (string) The name of the layer for which solutions should be computed. If the simulation objects do not have layer matching the provided name, then no solve is performed for that object. + Sa, Sb, ... + (Simulation object) The set of Simulation objects for which solutions are computed. It is useful to use the :func:`Clone` method to make copies. + + Return values: + + None. + +.. function:: ConvertUnits(value, from_units, to_units) + + Performs unit conversions. + + Usage:: + + S4.ConvertUnits(value, from_units, to_units) + + Arguments: + + value= + (number) The value to convert. + from_units, to_units + (string) The units in which `value` is currently expressed, and the desired units. + Currently supported units: + + Lengths: "um", "nm", "m", "cm", "mm" + Energies: "eV", "J" + Frequencies: "THz", "GHz", "Hz", "rad/s" + + Return values: + + The converted value, or nil if no conversion was possible. + +.. function:: Integrate(func, range1, range2, ..., opts) + + Performs adaptive numerical integration in an arbitrary number of dimensions. + + Usage:: + + integral,error = S4.Integrate(func, range1, range2, ..., opts) + + Arguments: + + func + (function) The function to integrate. It should take a number of arguments matching the number of range parameters passed in (the number of independent variables), and return a single number. + range1, range2, ... + (table) Each table should contain two elements corresponding to lower and upper limits of integration for the corresponding variable. + opts + (table) Options to the integration routine. This table is distinguished from an integration limit range by the presence of string keys. The options are: + + MaxEval + (integer) Default is 1000000. Places an upper limit on the number of function evaluations allowed. + AbsoluteError + (number) Default is 0. Sets the termination criterion for the absolute error in the integral. + RelativeError + (number) Default is 1e-6. Sets the termination criterion for the relative error in the integral. + Parallelize + (boolean) Default is false. If true, the integrand may be evaluated in parallel. In this case, the function must accept an integer as the first argument corresponding to the number of evaluations required, and subsequent parameters are tables containing the set of independent variables for each evaluation. The function should then return a table containg all the results in the same order. + + Return values: + + Returns the integrated value and an estimate of the error. + +.. data:: arg + + When used with the `-a` switch, the value of ``S4.arg`` is set to the command line switch argument. + This is a convenient way of passing command line arguments to S4 scripts, or in parallel environments for specifying machine IDs. + + When no command line switch is specified, ``S4.arg`` is nil. + + Multiple variables may be passed in by passing in multiple Lua statements:: + + ./S4 -a "a=1;b=2;c=3" input.lua + + Then within the script, the variables may be set with the statement:: + + pcall(loadstring(S4.arg)) + + +.. data:: MPIRank + + On a version of S4 with MPI support, gives the MPI machine rank (0-based index of processor node). For versions without MPI support, this is always 0. + +.. data:: MPISize + + On a version of S4 with MPI support, gives the MPI size (total number of processor nodes). For versions without MPI support, this is always 1. + +Simulation object +----------------- + +.. class:: Simulation + + The Simulation object is the primary object which computes solutions to systems. + When a new Simulation object is requested from :func:`NewSimulation`, all settings are in a blank state, with no materals, layers, or excitation. + When solutions are requested, only a minimal set of internal computations are performed in order to satisfy the request. + + +Parameter specification +^^^^^^^^^^^^^^^^^^^^^^^ + +.. method:: Simulation:SetLattice(L) + Simulation:SetLattice({x1,y1}, {x2,y2}) + + Sets the real-space lattice vectors. + + Usage:: + + S:SetLattice(L) + S:SetLattice({x1,y1}, {x2,y2}) + + Arguments: + + This function can take a single numeric argument, which sets the period for a 1D lattice. + This function can also take two table arguments, each of which must have two numeric elements. + The first table specifies the x- and y-coordinates of the first lattice basis vector, while the second table specifies the second basis vector. The basis vectors should have positive orientation (the cross product of the first with the second should yield a vector with positive z-coordinate). + + Return values: + + None + +.. method:: Simulation:SetNumG(n) + + Sets the maximum number of in-plane (x and y) Fourier expansion orders to use. + All fields and eigenmodes of the system use the same Fourier basis of the same dimension. + + The computation time is roughly proportional to the cube of this number, and the memory usage is roughly proportional to the square. + + Usage:: + + S:SetNumG(n) + + Arguments: + + n + (integer) The desired maximum number of Fourier orders to use. This number is an upper bound because internally, the Fourier lattice k-vectors (referred to as the G-vectors) are found in a symmetry-preserving manner starting from the origin and retaining those of shortest length. To obtain the actual number of Fourier orders used, use :func:`GetNumG`. + + Return values: + + None + +.. method:: Simulation:AddMaterial(name, {eps_r, eps_i}) + Simulation:AddMaterial(name, eps_tensor) + + Adds a new material with a specified dielectric constant. + + Usage:: + + S:AddMaterial(name, {eps_r, eps_i}) + S:AddMaterial(name, { + {xx_r, xx_i}, {xy_r, xy_i}, {xz_r, xz_i}, + {yx_r, yx_i}, {yy_r, yy_i}, {yz_r, yz_i}, + {zx_r, zx_i}, {zy_r, zy_i}, {zz_r, zz_i} + }) + + Arguments: + + name + (string) The name of the material. Each material must have a unique name. + eps_r, eps_r + (number) The real and imaginary parts of the relative permittivity of the material. The imaginary part should be positive. + xx_r, xx_i, xy_r, ... + (number) Components of the relative permittivity tensor of the material. Currently the xz, yz, zx, and zy components are ignored and assumed to be zero. + + Return values: + + None + +.. method:: Simulation:SetMaterial(name, {eps_r, eps_i}) + Simulation:SetMaterial(name, eps_tensor) + + Updates an existing material with a new dielectric constant or adds a material if none exists. + + Usage:: + + S:SetMaterial(name, {eps_r, eps_i}) + S:SetMaterial(name, { + {xx_r, xx_i}, {xy_r, xy_i}, {xz_r, xz_i}, + {yx_r, yx_i}, {yy_r, yy_i}, {yz_r, yz_i}, + {zx_r, zx_i}, {zy_r, zy_i}, {zz_r, zz_i} + }) + + Arguments: + + name + (string) The name of the material to update, or the name of a new material if no material by that name exists. + eps_r, eps_r + (number) The real and imaginary parts of the relative permittivity of the material. The imaginary part should be positive. + xx_r, xx_i, xy_r, ... + (number) Components of the relative permittivity tensor of the material. Currently the xz, yz, zx, and zy components are ignored and assumed to be zero. + + Return values: + + None + +.. method:: Simulation:AddLayer(name, thickness, material) + + Adds a new unpatterned layer with a specified thickness and material. + + Usage:: + + S:AddLayer(name, thickness, material) + + Arguments: + + name + (string) The name of the layer. Each layer must have a unique name. + thickness + (number) The thickness of the layer. + material + (string) The name of the material which comprises the layer. With patterning, this is the default (background) material of the layer. + + Return values: + + None + +.. method:: Simulation:SetLayer(name, thickness, material) + + Updates an existing layer with a new thickness and removes all layer patterning. + If no matching layer is found, adds a new unpatterned layer with a specified thickness and material. + The behavior is undefined if the new material does not match the old material during an update (currently, the new material is ignored, but this may change in the future). + If only the thickness needs to be modified, use :func:`SetLayerThickness`. + + Usage:: + + S:SetLayer(name, thickness, material) + + Arguments: + + name + (string) The name of the layer to update. If no layer by that name exists, a new layer is created with this name. + thickness + (number) The new thickness of the layer. + material + (string) The name of the material which comprises the layer. + + Return values: + + None + +.. method:: Simulation:SetLayerThickness(name, thickness) + + Updates an existing layer with a new thickness. + Previously cached layer eigenmodes are preserved, making this function the preferred way to update a layer's thickness. + + Usage:: + + S:SetLayerThickness(name, thickness) + + Arguments: + + name + (string) The name of the layer to update. + thickness + (number) The new thickness of the layer. + + Return values: + + None + +.. method:: Simulation:AddLayerCopy(name, thickness, original_name) + + Adds a new layer with a specified thickness, but identical patterning as another existing layer. + Note that this merely creates a reference to the copied layer; further patterning of the copied layer also affects the new layer. Additionally, a copy of a copy cannot be made. + + Usage:: + + S:AddLayerCopy(name, thickness, original_name) + + Arguments: + + name + (string) The name of the new layer, different from the layer being copied. + thickness + (number) The thickness of the new layer. + original_name + (string) The name of the layer which whose pattern is to be copied. That layer cannot itself be a copy of a layer. + + Return values: + + None + +.. method:: Simulation:SetLayerPatternCircle(layer, material, center, radius) + + Adds a (filled) circle of a specified material to an existing non-copy layer. + The circle should not intersect any other patterning shapes, but may contain or be contained within other shapes. + + Usage:: + + S:SetLayerPatternCircle(layer, material, center, radius) + + Arguments: + + layer + (string) The name of the layer to pattern. This layer cannot be a copy of another layer. + material + (string) The name of the material which fills the interior of the circle. + center + (numeric table, length 2) x- and y-coordinates of the center of the circle relative to the center of the unit cell (the origin). + radius + (number) Radius of the circle. + + Return values: + + None + +.. method:: Simulation:SetLayerPatternEllipse(layer, material, center, angle, halfwidths) + + Adds a (filled) ellipse of a specified material to an existing non-copy layer. + The ellipse should not intersect any other patterning shapes, but may contain or be contained within other shapes. + + Usage:: + + S:SetLayerPatternEllipse(layer, material, center, angle, halfwidths) + + Arguments: + + layer + (string) The name of the layer to pattern. This layer cannot be a copy of another layer. + material + (string) The name of the material which fills the interior of the ellipse. + center + (numeric table, length 2) x- and y-coordinates of the center of the ellipse relative to the center of the unit cell (the origin). + angle + (number) The angle (in degrees) by which the x-axis of the ellipse should be rotated (CCW). + halfwidths + (numeric table, length 2) The lengths of the semi-major axes of the ellipse. For an angle of 0, the first length is the semi-major axis in the x-direction, and the second length is the semi-major axis in the y-direction. + + Return values: + + None + +.. method:: Simulation:SetLayerPatternRectangle(layer, material, center, angle, halfwidths) + + Adds a (filled) rectangle of a specified material to an existing non-copy layer. + The rectangle should not intersect any other patterning shapes, but may contain or be contained within other shapes. + + Usage:: + + S:SetLayerPatternRectangle(layer, material, center, angle, halfwidths) + + Arguments: + + layer + (string) The name of the layer to pattern. This layer cannot be a copy of another layer. + material + (string) The name of the material which fills the interior of the rectangle. + center + (numeric table, length 2) x- and y-coordinates of the center of the rectangle relative to the center of the unit cell (the origin). + angle + (number) The angle (in degrees) by which the x-axis of the rectangle should be rotated (CCW). + halfwidths + (numeric table, length 2) The half-widths of the rectangle. For an angle of 0, the first length is half the width of the rectangle in the x-direction, and the second length is half the height in the y-direction. + + Return values: + + None + + +.. method:: Simulation:SetLayerPatternPolygon(layer, material, center, angle, vertices) + + Adds a (filled) polygon of a specified material to an existing non-copy layer. + The polygon should not self-intersect nor intersect any other patterning shapes, but may contain or be contained within other shapes. The polygon must also be specified with positive orientation (the vertices circle CCW about an interior point). + + Usage:: + + S:SetLayerPatternPolygon(layer, material, center, angle, vertices) + + Arguments: + + layer + (string) The name of the layer to pattern. This layer cannot be a copy of another layer. + material + (string) The name of the material which fills the interior of the polygon. + center + (numeric table, length 2) x- and y-coordinates of the center of the polygon relative to the center of the unit cell (the origin). + angle + (number) The angle (in degrees) by which the polygon should be rotated (CCW). + vertices + (numeric table, length 2*vertex_count) The x- and y-coordinates of the vertices of the (unrotated) polygon, one after another. + Thus, ``vertices[1]`` is the x-coordinate of the first vertex and ``vertices[2]`` is its y-coordinate, and ``vertices[3]`` is the x-coordinate of the second vertex, etc. + + Return values: + + None + + +.. method:: Simulation:SetExcitationPlanewave({phi,theta}, {s_amp, s_phase}, {p_amp, p_phase}, order) + + Sets the excitation to be a planewave incident upon the front (first layer specified) of the structure. + If both tilt angles are specified to be zero, then the planewave is normally incident with the electric field polarized along the x-axis for the p-polarization. + The phase of each polarization is defined at the origin (z = 0). + + Usage:: + + S:SetExcitationPlanewave({phi,theta}, {s_amp, s_phase}, {p_amp, p_phase}, order) + + Arguments: + + phi, theta + (number) Angles in degrees. ``phi`` and ``theta`` give the spherical coordinate angles of the planewave k-vector. + For zero angles, the k-vector is assumed to be (0, 0, kz), while the electric field is assumed to be (E0, 0, 0), and the magnetic field is in (0, H0, 0). + The angle ``phi`` specifies first the angle by which the E,H,k frame should be rotated (CW) about the y-axis, and the angle ``theta`` specifies next the angle by which the E,H,k frame should be rotated (CCW) about the z-axis. Note the different directions of rotations for each angle. + s_amp, p_amp + (number) The electric field amplitude of the s- and p-polarizations of the planewave. + s_phase, p_phase + (number) The phase of the s- and p-polarizations of the planewave, relative to z = 0 (the beginning of the first layer). + order + (number) An optional positive integer specifying which order (mode index) to excite. Defaults to 1. This is the same index that GetDiffractionOrder returns. + + Return values: + + None + +.. method:: Simulation:SetExcitationExterior(table) + + Low level function to set excitations by a superposition of incident modes of the exterior layers. For unpatterned layers, the incident modes are forward propagating planewaves in the front, and backward propagating planewaves in the back. + + Usage:: + + S:SetExcitationExterior{ + { G-index, pol, { amp-re, amp-im } }, + ... + } + + Arguments: + + G-index + (number) Index of the mode. This is the same index that GetDiffractionOrder returns. + pol + (string) Either 'x' or 'y' for the polarization of the electric field in unpatterned layers. + amp-re, amp-im + (number) Real and imaginary parts of the amplitude coefficient for the mode. + + Return values: + + None + +.. method:: Simulation:SetFrequency(freqr, freqi = 0) + + Sets the operating frequency of the system (and excitation). + + Usage:: + + S:SetFrequency(freqr, freqi) + + Arguments: + + freqr + (number) The (real) frequency of the excitation. This is not the angular frequency (the angular frequency is 2pi times of this). + freqi + (number) The imaginary frequency of the system. This parameter is typically not specified and assumed to be zero. When specified (typically for mode solving), this parameter should be negative for a physical (decaying in time) system. + + Return values: + + None + +Outputs requiring no solutions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. method:: Simulation:GetReciprocalLattice() + + Retrieves the reciprocal lattice basis vectors. + The vectors lack the scaling by 2pi (multiply them by 2pi to obtain the true reciprocal lattice basis vectors). + + Usage:: + + Gu,Gv = S:GetReciprocalLattice() + + Arguments: + + None. + + Return values: + + Gu, Gv + The first and second reciprocal lattice basis vectors. + Their relative geometric orientation is the same as the lattice specified with :func:`SetLattice`. + Each vector is a table of length 2, holding the x- and y-coordinates of the vector. + + +.. method:: Simulation:GetEpsilon({x, y, z}) + + Retrieves the dielectric constant at a particular point in the system by reconstructing the Fourier series using the G-vectors of the system. + + Note that this reconstruction is not representative of the actual dielectric constant profile used in simulations (such a notion is not meaningful). The reconstruction is created using the closed-form Fourier series coefficients of the specified patterning, summed over the terms comprising the G-vector list obtained from lattice truncation. This function exists to provide an intuitive sense for the spatial resolution of a particular G-vector truncation order. + + Usage:: + + eps_r, eps_i = S:GetEpsilon({x, y, z}) + + Arguments: + + x, y, z + (number) The coordinates of the point at which to retrieve the dielectric constant. + + Return values: + + eps_r, eps_i + The real and imaginary parts of the dielectric constant. + +.. method:: Simulation:OutputLayerPatternDescription(name, filename) + + Outputs a list of PostScript commands to render the exact layer pattern description from the specified patterning commands. Assumes letter-sized paper. + + Usage:: + + S:OutputLayerPatternDescription(name, filename) + + Arguments: + + name + (string) Name of the layer whose pattern description should be output. + filename + (string, optional) Filename to which the description should be output. If this argument is not provided, standard output is used. + + Return values: + + None. + +.. method:: Simulation:OutputLayerPatternRealization(name, Nu, Nv, filename) + + Outputs a Gnuplot format dump of the Fourier series reconstruction of the dielectric constant in the unit cell. Note that the output will appear distorted for non-orthogonal unit cells. + + Note that this reconstruction is not representative of the actual dielectric constant profile used in simulations (such a notion is not meaningful). The reconstruction is created using the closed-form Fourier series coefficients of the specified patterning, summed over the terms comprising the G-vector list obtained from lattice truncation. This function exists to provide an intuitive sense for the spatial resolution of a particular G-vector truncation order. + + Usage: + + S:OutputLayerPatternRealization(name, Nu, Nv, filename) + + Arguments: + + name + The name of the layer whose pattern should be output. + Nu, Nv + The number of discretization cells in the first and second lattice basis direction to use. The total number of output points is ``Nu*Nv``. + filename + (string, optional) Filename to which the pattern should be output. If this argument is not provided, standard output is used. + + Return values: + + None. + +Outputs requiring solutions +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. method:: Simulation:OutputStructurePOVRay([filename]) + + Outputs a `POV-Ray `_ script that will render one unit cell of the structure in 3D. Materials named ``air`` or ``vacuum`` (case insensitive) will be completely transparent. + + Usage:: + + S:OutputStructurePOVRay(filename) + + Arguments: + + filename + (string, optional) Filename to which the structure should be output. If this argument is not provided, standard output is used. + + Return values + + None. + +.. method:: Simulation:GetNumG() + + Returns the specified number of Fourier series orders to use (number of G-vectors), or, if a solution has been computed, the actual number of G-vectors used. + + Usage:: + + n = S:GetNumG() + + Arguments: + + None. + + Return values: + + n + If no solutions have been computed, the upper bound of G-vectors specified. If a solution has been computed, then ``n`` is the actual number of G-vectors used. + +.. method:: Simulation:GetGList() + + Returns a table of reciprocal lattice coordinates of the Fourier series orders used. + The coordinates are in the reciprocal lattice basis, and so they are integers. + + Usage:: + + G = S:GetGList() + + Arguments: + + None. + + Return values: + + G + A table of tables of length 2 holding the pairs of integer recprical lattice coordinates. + + +.. method:: Simulation:GetDiffractionOrder(m, n) + + Returns the index (1-based) of a particular diffraction order. + The index can be used directly in GetPowerFluxByOrder to obtain the diffracted power of a particular order. + The coordinate arguments are in the reciprocal lattice basis, and so they are integers. + A particular diffraction order is only a meaningful concept in a uniform (unpatterned) layer, otherwise the diffraction order corresponds to an arbitrary layer eigenfunction index. + + Usage:: + + i = S:GetDiffractionOrder(m, n) + + Arguments: + + m, n + (integer) The diffracted order. These numbers are in the reciprocal lattice basis. + + Return values: + + i + The index of the diffraction order. + +.. method:: Simulation:GetAmplitudes(layer, offset) + + Returns the raw mode amplitudes within a particular layer. + For uniform (unpatterned) layers, the modes are simply the diffracted orders, and the indexing of the returned amplitudes corresponds to the value obtained from GetDiffractedOrder. + The first value is guaranteed to be the straight transmitted or specularly reflected diffraction order. + For patterned layers, there is typically no meaningful information in these amplitudes. + + Usage:: + + forw,back = S:GetAmplitudes(layer, offset) + + Arguments: + + layer + (string) The name of the layer in which to obtain mode amplitudes. + offset + (number) The z-offset at which to obtain the mode amplitudes. + + Return values: + + forw,back + Tables of length 2*NumG containing the complex amplitudes of each forward and backward mode. Each complex amplitude is a table of length 2 containing real and imaginary parts. + + +.. method:: Simulation:GetPowerFlux(layer, offset=0) + + Returns the integral of the power (Poynting) flux density over a unit cell surface normal to the z-direction. + In other words, the z-component of the power flux is returned. + + Usage:: + + forw_r, back_r, forw_i, back_i = S:GetPowerFlux(layer, offset) + + Arguments: + + layer + (string) The name of the layer in which the integration surface lies. + offset + (number, optional) The z-offset of the integration surface from the beginning of the layer. This only matters for lossy layers. + + Return values: + + forw_r, forw_i + The real and imaginary parts of the forward component of the complex Poynting vector. Note that the result is not time averaged (no factor of 0.5 multiplied in). The forward component is defined as (E_total^* x H_forw + H_total^* x E_forw) / 2, where E_forw and H_forw are the fields reconstructed from only the forward propagating waveguide modes of the layer. + back_r, back_i + The real and imaginary parts of the backward component of the complex Poynting vector. Note that the result is not time averaged (no factor of 0.5 multiplied in). An analogous definition of the backward component of the Poynting vector follows from above. + +.. method:: Simulation:GetPowerFluxByOrder(layer, offset) + + Returns the integral of the power (Poynting) flux density over a unit cell surface normal to the z-direction for each Fourier series order. + In other words, the z-component of the Poynting flux for each order is returned. + + Usage:: + + P = S:GetPowerFluxByOrder(layer, offset) + + Arguments: + + layer + (string) The name of the layer in which the integration surface lies. + offset + (number) The z-offset of the integration surface from the beginning of the layer. This only matters for lossy layers. + + Return values: + + P + A table with length equal to the number of Fourier series orders used. + Each entry of the table is a table of length 4, whose values are: forw_r, back_r, forw_i, back_i. + These four quantities are described in the section for :func:`GetPowerFlux`. + + +.. method:: Simulation:GetStressTensorIntegral(layer, offset) + + Returns the integral of the electromagnetic stress tensor over a unit cell surface normal to the z-direction. + + Usage:: + + Txr, Tyr, Tzr, Txi, Tyi, Tzi = S:GetStressTensorIntegral(layer, offset) + + Arguments: + + layer + (string) The name of the layer in which the integration surface lies. + offset + (number) The z-offset of the integration surface from the beginning of the layer. + + Return values: + + Txr, Txi + The real and imaginary parts of the x-component of the stress tensor integrated over the specified surface, assuming a unit normal vector in the +z direction. Note that the result is not time averaged (no factor of 0.5 multiplied in). + Tyr, Tyi, Tzr, Tzi + Analogous to above. + + +.. method:: Simulation:GetLayerEnergyDensityIntegral(layer) + + Returns the volume integral of the electromagnetic energy density (epsilon*\|E\|^2 + \|H\|^2) over a unit cell throughout the entire thickness of a layer. + + Usage:: + + Ur,Ui = S:GetLayerEnergyDensityIntegral(layer) + + Arguments: + + layer + (string) The name of the layer in which to integrate over. + + Return values: + + Ur,Ui + The real and imaginary parts of the integral of the energy density throughout the volume of the layer's unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in). + + +.. method:: Simulation:GetLayerElectricEnergyDensityIntegral(layer) + + Returns the volume integral of the electric energy density (epsilon*\|E\|^2) over a unit cell throughout the entire thickness of a layer. + + Usage:: + + Ur,Ui = S:GetLayerElectricEnergyDensityIntegral(layer) + + Arguments: + + layer + (string) The name of the layer in which to integrate over. + + Return values: + + U + The real and imaginary parts of the integral of the electric energy density throughout the volume of the layer's unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in). + + +.. method:: Simulation:GetLayerMagneticEnergyDensityIntegral(layer) + + Returns the volume integral of the magnetic energy density (\|H\|^2) over a unit cell throughout the entire thickness of a layer. + + Usage:: + + Ur,Ui = S:GetLayerMagneticEnergyDensityIntegral(layer) + + Arguments: + + layer + (string) The name of the layer in which to integrate over. + + Return values: + + Ur,Ui + The real and imaginary parts of the integral of the magnetic energy density throughout the volume of the layer's unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in). + + +.. method:: Simulation:GetLayerElectricFieldIntensityIntegral(layer) + + Returns the volume integral of the squared electric field intensity (\|E\|^2) over a unit cell throughout the entire thickness of a layer. + + Usage:: + + Ur,Ui = S:GetLayerElectricFieldIntensityIntegral(layer) + + Arguments: + + layer + (string) The name of the layer in which to integrate over. + + Return values: + + Ur,Ui + The real and imaginary parts of the integral of the square electric field intensity throughout the volume of the layer's unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in). + +.. method:: Simulation:GetLayerZIntegral(layer, {x, y}) + + Returns the line integral along z (depth direction) of the squared magnitudes of electric and magnetic field components (\|Ex\|^2, \|Ey\|^2, etc.) throughout the entire thickness of a layer. + + Usage:: + + IEx, IEy, IEz, IHx, IHy, IHz = S:GetLayerZIntegral(layer, {x, y}) + + Arguments: + + layer + (string) The name of the layer in which to integrate through. + x,y + (number) The in-plane coordinates at which to integrate. + + Return values: + + IEx,IEy,IEz,IHx,IHy,IHz + The integral of the squared magnitudes of electric and magnetic field components throughout the thickness of the layer. Note that the result is not time averaged (no factor of 0.5 multiplied in). + + +.. method:: Simulation:GetEField({x, y, z}) + + Returns the electric field at a particular point within the structure. + + Usage:: + + Exr, Eyr, Ezr, Exi, Eyi, Ezi = S:GetEField({x, y, z}) + + Arguments: + + x, y, z + (number) The coordinates of the point at which to obtain the field. + + Return values: + + Exr, Exi + The real and imaginary parts of the complex electric field at the specified point. Note that the result is not time averaged (no factor of 0.5 multiplied in). + Eyr, Eyi, Ezr, Ezi + Analogous to above. + +.. method:: Simulation:GetHField({x, y, z}) + + Returns the magnetic field at a particular point within the structure. + + Usage:: + + Hxr, Hyr, Hzr, Hxi, Hyi, Hzi = S:GetHField({x, y, z}) + + Arguments: + + x, y, z + (number) The coordinates of the point at which to obtain the field. + + Return values: + + Hxr, Hxi + The real and imaginary parts of the complex magnetic field at the specified point. Note that the result is not time averaged (no factor of 0.5 multiplied in). + Hyr, Hyi, Hzr, Hzi + Analogous to above. + +.. method:: Simulation:GetFields({x, y, z}) + + Returns the electric and magnetic field at a particular point within the structure. + Note that it is more efficient to call this function when both fields are needed. + + Usage:: + + Exr, Eyr, Ezr, Hxr, Hyr, Hzr, Exi, Eyi, Ezi, Hxi, Hyi, Hzi = S:GetFields({x, y, z}) + + Arguments: + + x, y, z + (number) The coordinates of the point at which to obtain the field. + + Return values: + + Exr, Exi + The real and imaginary parts of the complex electric field at the specified point. Note that the result is not time averaged (no factor of 0.5 multiplied in). + Eyr, Eyi, Ezr, Ezi, Hxr, Hxi, Hyr, Hyi, Hzr, Hzi + Analogous to above. + +.. method:: Simulation:GetFieldPlane(z, {nu, nv}, format, basefilename) + + Returns the electric and magnetic fields on a regular grid over the unit cell (fundamental parallelogram) at a particular z coordinate. + It is more efficient to use this function than :func:`GetFields`. + + Usage:: + + E,H = S:GetFieldPlane(z, {nu, nv}, 'Array') + S:GetFieldPlane(z, {nu, nv}, 'FileWrite', basename) + S:GetFieldPlane(z, {nu, nv}, 'FileAppend', basename) + + Arguments: + + z + (number) The z-coordinate of the plane on which to obtain the field. + nu,nv + (integer) The number of sample points to use in each lattice vector direction. + format + (string) Specifies the format of the output. Current choices are: + + Array + Returns a pair of arrays of dimension `nu` by `nv`, each element is a table of length 3, containing tables of length 2 with the real and imaginary parts of the E or H field components. + FileWrite + Outputs the field data to files, overwriting the files. + FileAppend + Outputs the field data to files, appending to the files. This is useful of volume fields are needed. + + basefilename + (string) The base filename for file output. The outputs are named ``basefilename .. '.E'`` and ``basefilename .. '.H'``. + + Return values: + + E,H + Only returned if format is 'Array'. + Arrays of dimension `nu` by `nv`, each element is a table of length 3, containing tables of length 2 with the real and imaginary parts of the E or H field. + + +.. method:: Simulation:GetSMatrixDeterminant() + + Returns the determinant of the S-matrix (scattering matrix) of the entire structure. + The determinant is an analytic function in the complex frequency plane and has poles at the complex modal frequencies of the system. + + Usage:: + + mantr, manti, base, expo = S:GetSMatrixDeterminant() + + Arguments: + + None. + + Return values: + + mantr, manti + The determinant typically causes overflow or underflow, so it is returned as a mantissa multiplying a base raised to an exponent. These values are the real and imaginary parts of the mantissa. The value of the determinant is (mantr+i*manti)*base^expo. + base + The base of the determinant representation (see above). + expo + The exponent of the determinant representation (see above). + + + +Options +^^^^^^^ + +.. method:: Simulation:UseLanczosSmoothing(use) + + Enables or disables smoothing of the Fourier series representations of the layer dielectric constants using the Lanczos sigma factor (box filtering). This reduces the Gibbs phenomenon ringing in the real space reconstruction. + + Usage:: + + S:UseLanczosSmoothing(use) + + Arguments: + + use + (boolean, optional) Indicates whether to enable smoothing. If this argument is not provided, smoothing is enabled. + + Return values: + + None. + + +.. method:: Simulation:UseDiscretizedEpsilon(use) + + Enables or disables the use of discretization in generating the Fourier coefficients of the in-plane epsilon profiles, instead of using values from closed-form equations. When enabled, the coefficients are obtained by FFT. + + See the :ref:`fmm-formulations-label` for details. + + Usage:: + + S:UseDiscretizedEpsilon(use) + + Arguments: + + use + (boolean, optional) Indicates whether to use a discretized epsilon. If this argument is not provided, use of a discretized epsilon is enabled. + + Return values: + + None. + + +.. method:: Simulation:UsePolarizationDecomposition(use) + + Enables or disables the use of proper in-plane Fourier factorization rules by decomposing fields into a polarization basis which conforms to the material boundaries. + The polarization basis field is generated automatically by computing a quasi-harmonic vector field everywhere tangent to the layer pattern boundaries. + This option is not guaranteed to work in the presence of tensor dielectric constants. + + Enabling this feature typically improves convergence with respect to the number of G-vectors. + See the :ref:`fmm-formulations-label` for details. + + Usage:: + + S:UsePolarizationDecomposition(use) + + Arguments: + + use + (boolean, optional) Indicates whether to enable polarization decomposition. If this argument is not provided, polarization decomposition is enabled. + + Return values: + + None. + +.. method:: Simulation:UseSubpixelSmoothing(use) + + Enables or disables the use of second-order accurate epsilon averaging rules within a pixel. + The average epsilon within a pixel is computed using the fill factor of each material and the interface direction. + + Enabling this feature may improve convergence with respect to the number of G-vectors. + See the :ref:`fmm-formulations-label` for details. + + Usage:: + + S:UseSubpixelSmoothing(use) + + Arguments: + + use + (boolean, optional) Indicates whether to enable subpixel smoothing. If this argument is not provided, subpixel smoothing is enabled. + + Return values: + + None. + +.. method:: Simulation:UseJonesVectorBasis(use) + + This option only has an effect with :func:`UsePolarizationDecomposition`. + When enabled, a Jones vector basis field is used instead of a conformal harmonic field. + + Enabling this feature may improve convergence with respect to the number of G-vectors. + See the :ref:`fmm-formulations-label` for details. + + Usage:: + + S:UseJonesVectorBasis(use) + + Arguments: + + use + (boolean, optional) Indicates whether to use a Jones vector basis. If this argument is not provided, use of a Jones vector basis is enabled. + + Return values: + + None. + +.. method:: Simulation:UseNormalVectorBasis(use) + + This option only has an effect with :func:`UsePolarizationDecomposition`. + When enabled, the resulting vector field is normalized. Where the vector field is zero, the unit vector in the x-direction is used. + + Enabling this feature may improve convergence with respect to the number of G-vectors. + See the :ref:`fmm-formulations-label` for details. + + Usage:: + + S:UseNormalVectorBasis(use) + + Arguments: + + use + (boolean, optional) Indicates whether to use a normalized vector basis. If this argument is not provided, use of a normalized vector basis is enabled. + + Return values: + + None. + +.. method:: Simulation:SetResolution(use) + + This option only has an effect with :func:`UseDiscretizedEpsilon` or :func:`UseSubpixelSmoothing`. + This function sets the resolution of the FFT grid and vector field generated by :func:`EnablePolarizationDecomposition`. + The resolution is multiplied by the largest G-vector extent (integer lattice coordinate), and should be at least 2 to satisfy the Nyquist limit. It is best to use a number with small integer factors in order for the FFT to be computed efficiently. The size of each dimension of the FFT is obviously proportional to this value. The default is 8. + + See the :ref:`fmm-formulations-label` for details. + + Usage:: + + S:SetResolution(n) + + Arguments: + + n + The oversampling factor. Must be at least 2. + + Return values: + + None. + +.. method:: Simulation:SetBasisFieldDumpPrefix(prefix) + + Setting this option to a filename prefix causes the vector field used by the polarization decomposition to be dumped to files (one for each layer) in Gnuplot format. + The files are named by concatenating the provided prefix string with each layer's name. + + Usage:: + + S:SetBasisFieldDumpPrefix(prefix) + + Arguments: + + prefix + (string, optional) When provided, the filename prefix is set to the given string. This can be an empty string. If this argument is not provided, the basis field dump is disabled. + + Return values: + + None. + +.. method:: Simulation:SetLatticeTruncation(trunc) + + Sets the type of lattice truncation to use when selecting G-vectors. + + Usage:: + + S:SetLatticeTruncation(trunc) + + Arguments: + + trunc + (string) Can be one of the following values: + + Circular + This is the default. The G-vectors are selected to have shortest length (by l2 norm). + Parallelogramic + Chooses the G-vectors within a parallelogram aligned with the reciprocal lattice basis. The number chosen will always be a perfect square of an odd number. + + Return values: + + None. + +.. method:: Simulation:SetVerbosity(level) + + Sets the level of diagnostic output generated by the program. + + Usage:: + + S:SetVerbosity(level) + + Arguments: + + level + (integer, optional) The larger this value, the more status output is generated. Valid values are in the range of 0-9, inclusive. A value of 0 disables all status output. + + Return values: + + None. + +.. method:: Simulation:UseLessMemory(use) + + Setting this option will prevent storage of certain intermediate results. This will save approximately 30% memory for non-trivial layers. + The drawback is slower computation of any output quantities that require solutions. + + Usage: + + S:UseLessMemory(use) + + Arguments: + + use + (boolean, optional) Indicates whether to use less memory. If this argument is not provided, lower memory usage is enabled. + + Return values: + + None. + + +Miscellaneous +^^^^^^^^^^^^^ + +.. method:: Simulation:Clone() + + Duplicates an existing Simulation object, copying all materials, layers, and excitation information. + No partial solution information is copied. + + Usage:: + + S2 = S:Clone() + + Arguments: + + None. + + Return values: + + A copy of the `Simulation object`_. + +SpectrumSampler object +---------------------- + +.. class:: SpectrumSampler + + The SpectrumSampler object provides a convenient way to sample spectral information of a system. + For example, it is used to resolve sharp peaks in transmission spectra. + Interaction with a SpectrumSampler object is by contract; a new frequency is retrieved from it by which simulation results at that frequency are computed, and then the results are submitted. + + The frequencies given out by a SpectrumSampler object aim to produce a visually pleasing plot of the resulting spectrum by limiting the maximum normalized bend angles between adjacent line segments of the plot. + + A typical usage is shown below:: + + function f(x) -- example function + return math.sin(x) + end + sampler = S4.NewSpectrumSampler(0.1, 0.9, -- start and end frequencies + { -- table of options + InitialNumPoints = 33, + RangeThreshold = 0.001, + MaxBend = math.cos(math.rad(10)), + MinimumSpacing = 1e-6 + }) + while not sampler:IsDone() do + x = sampler:GetFrequency() + y = f(x) -- compute the desired result + sampler:SubmitResult(y) + end + + spectrum = sampler:GetSpectrum() + for i,xy in ipairs(spectrum) do + print(xy[1],xy[2]) + end + +.. method:: SpectrumSampler:IsDone() + + Queries whether the SpectrumSampler has completed sampling. + When sampling has been completed, no further frequencies should be requested from the SpectrumSampler object, and no further results should be submitted. + + Usage:: + + done = sampler:IsDone() + + Arguments: + + None. + + Return values: + + A boolean value indicating whether sampling has completed. + + +.. method:: SpectrumSampler:GetFrequency() + + Retrieves the next frequency at which to sample the spectrum. This function should only be used if the SpectrumSampler object was created with `Parallize` set to false (the default). + + Usage:: + + freq = sampler:GetFrequency() + + Arguments: + + None. + + Return values: + + The (numeric) frequency at which the next result should be computed and submitted. + + +.. method:: SpectrumSampler:GetFrequencies() + + Retrieves the next set of frequencies at which to sample the spectrum. This function should only be used if the SpectrumSampler object was created with `Parallize` set to true. + + Usage:: + + freqlist = sampler:GetFrequency() + + Arguments: + + None. + + Return values: + + A list of (numeric) frequencies at which the next results should be computed and submitted. + +.. method:: SpectrumSampler:SubmitResult(result) + + Submits a result to the SpectrumSampler object. The result is assumed to be at the frequency of the last requested frequency. This function should only be used if the SpectrumSampler object was created with `Parallize` set to false (the default). + + Usage:: + + done = sampler:SubmitResult(result) + + Arguments: + + result + (number) The result to submit. The result may be any value (for example, the transmission through a structure). + + Return values: + + A boolean value indicating whether sampling has completed. + +.. method:: SpectrumSampler:SubmitResults(result_list) + + Submits a set of results to the SpectrumSampler object. The results are assumed to be at the frequencies of the last requested frequencies. This function should only be used if the SpectrumSampler object was created with `Parallize` set to true. + + Usage:: + + done = sampler:SubmitResults(result_list) + + Arguments: + + result_list + (table) The list of results to submit. The length of this table must match the number of frequencies obtained from the previous call to `GetFrequencies`. + + Return values: + + A boolean value indicating whether sampling has completed. + +.. method:: SpectrumSampler:GetSpectrum() + + Retrieves a list of all sampled frequencies and submitted results. + This function should only be used when the SpectrumSampler object indicates that sampling is complete. + + Usage:: + + valarray = sampler:GetSpectrum() + + Arguments: + + None. + + Return values: + + An array (with length equal to the number of samples) of pairs (arrays of length 2) containing the sampled frequency and corresponding submitted result. + + +Interpolator object +------------------- + +.. class:: Interpolator + + The Interpolator object provides a tool to perform various types of interpolation on data. + The most common use is to interpolate between experimentally determined values for dieletric constants. + A typical usage is shown below:: + + interpolator = S4.NewInterpolator('linear', { + {3.0, {14.2, 32}}, -- x, and list of y values + {5.4, {4.6, 10}}, + {5.7, {42.7, 20}}, + {8.0, {35.2, 40}} + }) + + for x = 0, 10, 0.1 do + y1, y2 = interpolator:Get(x) + print(x, y1, y2) + end + + At each x (abscissa) value, any number of y (ordinate) values can be specified for interpolation. + +.. method:: Interpolator:Get(x) + + Retrieves the interpolated ordinates for a given abscissa value. + + Usage:: + + y1, y2, ... = interpolator:Get(x) + + Arguments: + + x + (number) The abscissa value at which to interpolate. + + Return values: + + A list of interpolated ordinate values. + + +.. |S4| replace:: S\ :sup:`4` + diff --git a/doc/build/html/_sources/python_api.txt b/doc/build/html/_sources/python_api.txt new file mode 100644 index 0000000..0f34778 --- /dev/null +++ b/doc/build/html/_sources/python_api.txt @@ -0,0 +1,763 @@ +.. default-domain:: py + +.. _python-api-label: + +Python API reference +==================== + +|S4| can be built as a `Python `_ extension, in addition to the original `Lua `_ interface. +The current Python interface is not as fully featured as the Lua interface, but it should ultimately achieve feature parity. +Much auxilliary functionality, such as numerical integration, is not included here since `Numpy `_ and `Scipy `_ can easily be used instead. + +S4 module +--------- + +.. module:: S4 + +All top level functions of |S4| are located in the ``S4`` library. + +.. function:: New(Lattice, NumBasis) + + Returns a new `Simulation object`_. + + Usage:: + + S = S4.NewSimulation(Lattice=((1,0),(0,1)), NumBasis=100) + + Arguments: + + Lattice + Sets the lattice vectors for the structure. This can be a single real number in the case of a 1D periodic lattice, or a pair of vectors for a 2D periodic lattice. + NumBasis + Sets the maximum number of in-plane (x and y) Fourier expansion orders to use. + All fields and eigenmodes of the system use the same Fourier basis of the same dimension. + The computation time is roughly proportional to the cube of this number, and the memory usage is roughly proportional to the square. + This is equivalent to the "NumG" setting in the Lua interface. + + Return values: + + S + A new `Simulation object`_. + + +Simulation object +----------------- + +.. class:: Simulation + +The Simulation object is the primary object which computes solutions to systems. +When a new Simulation object is requested from :func:`New`, all settings are in a blank state, with no materals, layers, or excitation. +When solutions are requested, only a minimal set of internal computations are performed in order to satisfy the request. + +Parameter specification +^^^^^^^^^^^^^^^^^^^^^^^ + +.. method:: Simulation.SetMaterial(Name, Epsilon) + + Updates an existing material with a new dielectric constant or adds a material if none exists. + + Usage:: + + S.SetMaterial(Name = 'Silicon, Epsilon = 12+0.01j) + S.SetMaterial(Name = 'Silicon', Epsilon = ( + (12+0.01j, 0, 0), + (0, 12+0.01j, 0), + (0, 0, 12+0.01j) + )) + + Arguments: + + Name + (string) The name of the material to update, or the name of a new material if no material by that name exists. + Epsilon + (number, complex number, or 3x3 tensor) The relative permittivity of the material. The imaginary part should generally be positive for lossy materials. + + Return values: + + None + +.. method:: Simulation.AddLayer(Name, Thickness, Material) + + Adds a new unpatterned layer with a specified thickness and material. + + Usage:: + + S.AddLayer(Name = 'slab', Thickness = 0.6, Material = 'Silicon') + + Arguments: + + Name + (string) The name of the layer. Each layer should have a unique name if it is to be referenced later. + Thickness + (number) The thickness of the layer. + Material + (string) The name of the material which comprises the layer. With patterning, this is the default (background) material of the layer. + + Return values: + + None + +.. method:: Simulation.AddLayerCopy(Name, Thickness, Layer) + + Adds a new layer with a specified thickness, but identical patterning as another existing layer. + Note that this merely creates a reference to the copied layer; further patterning of the copied layer also affects the new layer. Additionally, a copy of a copy cannot be made. + + Usage:: + + S.AddLayerCopy(Name = 'slab2', Thickness = 0.5, Layer = 'slab') + + Arguments: + + Name + (string) The name of the new layer, different from the layer being copied. + Thickness + (number) The thickness of the new layer. + Layer + (string) The name of the layer which whose pattern is to be copied. That layer cannot itself be a copy of a layer. + + Return values: + + None + +.. method:: Simulation.SetLayerThickness(Layer, Thickness) + + Updates an existing layer with a new thickness. + Previously cached layer eigenmodes are preserved, making this function the preferred way to update a layer's thickness. + + Usage:: + + S.SetLayerThickness(Layer = 'slab', thickness) + + Arguments: + + Layer + (string) The name of the layer to update. + Thickness + (number) The new thickness of the layer. + + Return values: + + None + +.. method:: Simulation.RemoveLayerRegions(Layer) + + Removes all layer regions from an existing layer. + + Usage:: + + S.RemoveLayerRegions(Layer = 'slab') + + Arguments: + + Layer + (string) The name of the layer to modify. + + Return values: + + None + +.. method:: Simulation.SetRegionCircle(Layer, Material, Center, Radius) + + Adds a (filled) circle of a specified material to an existing non-copy layer. + The circle should not intersect any other patterning shapes, but may contain or be contained within other shapes. + + Usage:: + + S.SetRegionCircle( + Layer = 'slab', + Material = 'Vacuum', + Center = (0,0), + Radius = 0.2 + ) + + Arguments: + + Layer + (string) The name of the layer to pattern. This layer cannot be a copy of another layer. + Material + (string) The name of the material which fills the interior of the circle. + Center + (pair of numbers) x- and y-coordinates of the center of the circle relative to the center of the unit cell (the origin). + Radius + (number) Radius of the circle. + + Return values: + + None + +.. method:: Simulation.SetRegionEllipse(Layer, Material, Center, Angle, Halfwidths) + + Adds a (filled) ellipse of a specified material to an existing non-copy layer. + The ellipse should not intersect any other patterning shapes, but may contain or be contained within other shapes. + + Usage:: + + S.SetRegionEllipse( + Layer = 'slab', + Material = 'Vacuum', + Center = (0,0), + Angle = 30, # in degrees + Halfwidths = (0.3,0.4) # semi-axis lengths + ) + + Arguments: + + Layer + (string) The name of the layer to pattern. This layer cannot be a copy of another layer. + Material + (string) The name of the material which fills the interior of the ellipse. + Center + (numeric table, length 2) x- and y-coordinates of the center of the ellipse relative to the center of the unit cell (the origin). + Angle + (number) The angle (in degrees) by which the x-axis of the ellipse should be rotated (CCW). + Halfwidths + (pair of numbers) The lengths of the semi-major axes of the ellipse. For an angle of 0, the first length is the semi-major axis in the x-direction, and the second length is the semi-major axis in the y-direction. + + Return values: + + None + +.. method:: Simulation.SetRegionRectangle(Layer, Material, Center, Angle, Halfwidths) + + Adds a (filled) rectangle of a specified material to an existing non-copy layer. + The rectangle should not intersect any other patterning shapes, but may contain or be contained within other shapes. + + Usage:: + + S.SetRegionRectangle( + Layer = 'slab', + Material = 'Vacuum', + Center = (0,0), + Angle = 30, # in degrees + Halfwidths = (0.3,0.4) + ) + + Arguments: + + Layer + (string) The name of the layer to pattern. This layer cannot be a copy of another layer. + Material + (string) The name of the material which fills the interior of the rectangle. + Center + (numeric table, length 2) x- and y-coordinates of the center of the rectangle relative to the center of the unit cell (the origin). + Angle + (number) The angle (in degrees) by which the x-axis of the rectangle should be rotated (CCW). + Halfwidths + (pair of numbers) The half-widths of the rectangle. For an angle of 0, the first length is half the width of the rectangle in the x-direction, and the second length is half the height in the y-direction. + + Return values: + + None + + +.. method:: Simulation.SetRegionPolygon(Layer, Material, Center, Angle, Vertices) + + Adds a (filled) polygon of a specified material to an existing non-copy layer. + The polygon should not self-intersect nor intersect any other patterning shapes, but may contain or be contained within other shapes. The polygon must also be specified with positive orientation (the vertices circle CCW about an interior point). + + Usage:: + + S.SetRegionPolygon( + Layer = 'slab', + Material = 'Vacuum', + Center = (0,0), + Angle = 10, # in degrees + Vertices = ( + (0,0), + (0.2,0), + (0.2,0.2), + (0.1,0.2), + (0.1,0.1), + (0,0.1) + ) + ) + + Arguments: + + Layer + (string) The name of the layer to pattern. This layer cannot be a copy of another layer. + Material + (string) The name of the material which fills the interior of the polygon. + Center + (numeric table, length 2) x- and y-coordinates of the center of the polygon relative to the center of the unit cell (the origin). + Angle + (number) The angle (in degrees) by which the polygon should be rotated (CCW). + Vertices + (tuple of pairs) The x- and y-coordinates of the vertices of the (unrotated) polygon, one after another, in counter-clockwise order. + + Return values: + + None + + +.. method:: Simulation.SetExcitationPlanewave(IncidenceAngles, sAmplitude=0, pAmplitude=0, Order=0]) + + Sets the excitation to be a planewave incident upon the front (first layer specified) of the structure. + If both tilt angles are specified to be zero, then the planewave is normally incident with the electric field polarized along the x-axis for the p-polarization. + The phase of each polarization is defined at the origin (z = 0). + + Usage:: + + S.SetExcitationPlanewave( + IncidenceAngles=( + 10, # polar angle in [0,180) + 30 # azimuthal angle in [0,360) + ), + sAmplitude = 0.707+0.707j, + pAmplitude = 0.707-0.707j, + Order = 0 + ) + + Arguments: + + IncidenceAngles + (pair of numbers) Of the form (phi,theta) with angles in degrees. + ``phi`` and ``theta`` give the spherical coordinate angles of the planewave k-vector. + For zero angles, the k-vector is assumed to be (0, 0, kz), while the electric field is assumed to be (E0, 0, 0), and the magnetic field is in (0, H0, 0). The angle ``phi`` specifies first the angle by which the E,H,k frame should be rotated (CW) about the y-axis, and the angle ``theta`` specifies next the angle by which the E,H,k frame should be rotated (CCW) about the z-axis. + Note the different directions of rotations for each angle. + sAmplitude + (complex number) The electric field amplitude of the s-polarizations of the planewave. + pAmplitude + (complex number) The electric field amplitude of the p-polarizations of the planewave. + Order + (integer) An optional positive integer specifying which order (mode index) to excite. Defaults to 0. Refer to :func:`GetBasisSet` for details. + + Return values: + + None + +.. method:: Simulation.SetFrequency(freq) + + Sets the operating frequency of the system (and excitation). + + Usage:: + + S.SetFrequency(1.2) + + Arguments: + + freq + (complex number) The frequency of the excitation. This is not the angular frequency (the angular frequency is 2pi times of this). + If a complex number is specified (typically for mode solving), the imaginary part should be negative for a physical (decaying in time) system. + + Return values: + + None + +Outputs requiring no solutions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. method:: Simulation.GetReciprocalLattice() + + Retrieves the reciprocal lattice basis vectors. + The vectors lack the scaling by 2pi (multiply them by 2pi to obtain the true reciprocal lattice basis vectors). + + Usage:: + + (Gu,Gv) = S.GetReciprocalLattice() + + Arguments: + + None. + + Return values: + + Gu, Gv + The first and second reciprocal lattice basis vectors. + Their relative geometric orientation is the same as the lattice specified in :func:`New`. + Each vector is a tuple of length 2, holding the x- and y-coordinates of the vector. + +.. method:: Simulation.GetEpsilon(x, y, z) + + Retrieves the dielectric constant at a particular point in the system by reconstructing the Fourier series using the G-vectors of the system. + + Note that this reconstruction is not representative of the actual dielectric constant profile used in simulations (such a notion is not meaningful). The reconstruction is created using the closed-form Fourier series coefficients of the specified patterning, summed over the terms comprising the G-vector list obtained from lattice truncation. This function exists to provide an intuitive sense for the spatial resolution of a particular G-vector truncation order. + + Usage:: + + eps = S.GetEpsilon(0.1, 0.2, 0.3) + + Arguments: + + x, y, z + (number) The coordinates of the point at which to retrieve the dielectric constant. + + Return values: + + eps + The (usually complex) relative dielectric constant at the specified point. + +.. method:: Simulation.OutputLayerPatternPostscript(Layer[, Filename]) + + Outputs a list of PostScript commands to render the exact layer pattern description from the specified patterning commands. Assumes letter-sized paper. + + Usage:: + + S.OutputLayerPatternPostscript(Layer = 'slab', Filename = 'out.ps') + + Arguments: + + Layer + (string) Name of the layer whose pattern description should be output. + Filename + (string, optional) Filename to which the description should be output. If this argument is not provided, standard output is used. + + Return values: + + None. + +Outputs requiring solutions +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. method:: Simulation.OutputStructurePOVRay([Filename]) + + Outputs a `POV-Ray `_ script that will render one unit cell of the structure in 3D. Materials named ``air`` or ``vacuum`` (case insensitive) will be completely transparent. + Note that the output is not guaranteed to be correct or parsable by POV-Ray; it is only meant as a starting point to produce publication-ready figures. + + Usage:: + + S.OutputStructurePOVRay(Filename = 'out.pov') + + Arguments: + + Filename + (string, optional) Filename to which the structure should be output. If this argument is not provided, standard output is used. + + Return values: + + None. + +.. method:: Simulation.GetBasisSet() + + Returns a tuple of reciprocal lattice coordinates of the Fourier series orders used. + The coordinates are in the reciprocal lattice basis, and so they are integers. + + Usage:: + + Glist = S.GetBasisSet() + + Arguments: + + None. + + Return values + + Glist + A tuples of tuples of length 2 holding the pairs of integer recprical lattice coordinates. + + +.. method:: Simulation.GetAmplitudes(Layer, zOffset=0) + + Returns the raw mode amplitudes within a particular layer. + For uniform (unpatterned) layers, the modes are simply the diffracted orders, and the indexing of the returned amplitudes corresponds to the value obtained from GetDiffractedOrder. + The first value is guaranteed to be the straight transmitted or specularly reflected diffraction order. + For patterned layers, there is typically no meaningful information in these amplitudes. + + Usage:: + + (forw,back) = S.GetAmplitudes(Layer = 'substrate', zOffset = 0) + + Arguments: + + Layer + (string) The name of the layer in which to obtain mode amplitudes. + zOffset + (number) The z-offset at which to obtain the mode amplitudes. + + Return values: + + forw,back + Tuples of length 2*NumBasis containing the complex amplitudes of each forward and backward mode. + +.. method:: Simulation.GetPowerFlux(Layer, zOffset=0) + + Returns the integral of the power flux density over a unit cell surface normal to the z-direction. + In other words, the z-component of the integrated Poynting flux is returned. + + Usage:: + + (forw,back) = S.GetPowerFlux(Layer = 'substrate', zOffset = 0) + + Arguments: + + Layer + (string) The name of the layer in which the integration surface lies. + zOffset + (number, optional) The z-offset of the integration surface from the beginning of the layer. This only matters for lossy layers. + + Return values: + + forw + The forward component of the complex Poynting vector. Note that the result is not time averaged (no factor of 0.5 multiplied in). The forward component is defined as (E_total^* x H_forw + H_total^* x E_forw) / 2, where E_forw and H_forw are the fields reconstructed from only the forward propagating waveguide modes of the layer. + back + The backward component of the complex Poynting vector. Note that the result is not time averaged (no factor of 0.5 multiplied in). An analogous definition of the backward component of the Poynting vector follows from above. + +.. method:: Simulation.GetPowerFluxByOrder(Layer, zOffset=0) + + Returns the integral of the Poynting flux density over a unit cell surface normal to the z-direction for each Fourier series order. + In other words, the z-component of the Poynting flux for each order is returned. + + Usage:: + + P = S.GetPowerFluxByOrder(Layer = 'substrate', zOffset = 0) + + Arguments: + + Layer + (string) The name of the layer in which the integration surface lies. + zOffset + (number) The z-offset of the integration surface from the beginning of the layer. This only matters for lossy layers. + + Return values: + + P + A tuple with length equal to the number of Fourier series orders used. + Each entry of the is a pair (tuple) of forward and backward complex powers. + These power quantities are described in the section for :func:`GetPowerFlux`. + + +.. method:: Simulation:GetStressTensorIntegral(Layer, zOffset=0) + + Returns the integral of the electromagnetic stress tensor over a unit cell surface normal to the z-direction. + + Usage:: + + (Tx, Ty, Tz) = S.GetStressTensorIntegral(layer, offset) + + Arguments: + + Layer + (string) The name of the layer in which the integration surface lies. + zOffset + (number) The z-offset of the integration surface from the beginning of the layer. + + Return values: + + Tx,Ty,Tz + The real and imaginary parts of the x-, y-, and z-components of the stress tensor integrated over the specified surface, assuming a unit normal vector in the +z direction. Note that the result is not time averaged (no factor of 0.5 multiplied in). + +.. method:: Simulation.GetLayerVolumeIntegral(Layer, Quantity) + + Returns the volume integral of a particular density over a unit cell throughout the entire thickness of a layer. + + Usage:: + + I = S.GetLayerVolumeIntegral(Layer = 'slab', Quantity = 'U') + + Arguments: + + Layer + (string) The name of the layer in which to integrate over. + Quantity + (string) The quantity to integrate. Currently, the choices are: + + U + (epsilon*\|E\|^2 + \|H\|^2) + E + (epsilon*\|E\|^2) + H + (\|H\|^2) + e + (\|E\|^2) + + Return values: + + I + The complex integral of the density throughout the volume of the layer's unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in). + + +.. method:: Simulation:GetLayerZIntegral(Layer, xy) + + Returns the line integral along z (depth direction) of the squared magnitudes of electric and magnetic field components (\|Ex\|^2, \|Ey\|^2, etc.) throughout the entire thickness of a layer. + + Usage:: + + E,H = S.GetLayerZIntegral(Layer = 'slab', xy = (0.1, 0.2)) + + Arguments: + + Layer + (string) The name of the layer in which to integrate through. + xy + (pair of numbers) The in-plane coordinates at which to integrate. + + Return values: + + E,H + Tuples of length 3 containing the x-, y-, and z-components of the integrated squared magnitude of the E or H field throughout the thickness of the layer. Note that the result is not time averaged (no factor of 0.5 multiplied in). + + +.. method:: Simulation.GetFields(x, y, z) + + Returns the electric and magnetic field at a particular point within the structure. + + Usage:: + + (E,H) = S.GetFields(0.1, 0.2, 0.3) + + Arguments: + + x, y, z + (number) The coordinates of the point at which to obtain the field. + + Return values: + + E,H + Tuples of length 3 of the complex electric or magnetic field at the specified point. Note that the result is not time averaged (no factor of 0.5 multiplied in). + +.. method:: Simulation.GetFieldsOnGrid(z, NumSamples, Format, BaseFilename) + + Returns the electric and magnetic fields on a regular grid over the unit cell (fundamental parallelogram) at a particular z coordinate. + It is more efficient to use this function than :func:`GetFields`. + + Usage:: + + E,H = S.GetFieldsOnGrid(z = 0.2, NumSamples=(100,100), Format = 'Array') + S.GetFieldsOnGrid(z = 0.2, NumSamples=(100,100), Format = 'FileWrite', BaseFilename = 'field') + S.GetFieldsOnGrid(z = 0.2, NumSamples=(100,100), Format = 'FileAppend', BaseFilename = 'field') + + Arguments: + + z + (number) The z-coordinate of the plane on which to obtain the field. + NumSamples + (pair of integers) The number of sample points to use in each lattice vector direction. + Format + (string) Specifies the format of the output. Current choices are: + + Array + Returns a pair of (tuple) arrays of dimension `nu` by `nv`, each element is a tuple of length 3, containing complex numbers of the E or H field components. + FileWrite + Outputs the field data to files, overwriting the files. + FileAppend + Outputs the field data to files, appending to the files. This is useful of volume fields are needed. + + BaseFilename + (string) The base filename for file output. The outputs are named ``BaseFilename + '.E'`` and ``basefilename + '.H'``. + + Return values: + + E,H + Only returned if format is 'Array'. + Arrays (tuples) of dimension `nu` by `nv`, each element is a tuple of length 3, containing complex numbers of the E or H field components. + +.. method:: Simulation.GetSMatrixDeterminant() + + Returns the determinant of the S-matrix (scattering matrix) of the entire structure. + The determinant is an analytic function in the complex frequency plane and has poles at the complex modal frequencies of the system. + + Usage:: + + (mant, base, expo) = S.GetSMatrixDeterminant() + + Arguments: + + None. + + Return values: + + mant + The determinant typically causes overflow or underflow, so it is returned as a mantissa multiplying a base raised to an exponent. The value of the determinant is mant*base^expo. + base + The base of the determinant representation (see above). + expo + The exponent of the determinant representation (see above). + + +Options +^^^^^^^ + +.. method:: Simulation.SetOptions(...) + + Sets various options for a `Simulation object`_. The options are described below, and any option not specified is left unchanged. + + Usage:: + + S.SetOptions( # these are the defaults + Verbosity = 0, + LatticeTruncation = 'Circular', + DiscretizedEpsilon = False, + DiscretizationResolution = 8, + PolarizationDecomposition = False, + PolarizationBasis = 'Default', + LanczosSmoothing = False, + SubpixelSmoothing = False, + ConserveMemory = False + ) + + Arguments: + + Verbosity + (integer) The larger this value, the more status output is generated. Valid values are in the range of 0-9, inclusive. A value of 0 disables all status output. + LatticeTruncation + (string) Sets the type of lattice truncation to use when selecting G-vectors. Can be one of the following values: + + Circular + This is the default. The G-vectors are selected to have shortest length (by l2 norm). + Parallelogramic + Chooses the G-vectors within a parallelogram aligned with the reciprocal lattice basis. The number chosen will always be a perfect square of an odd number. + + DiscretizedEpsilon + (boolean) Enables or disables the use of discretization in generating the Fourier coefficients of the in-plane epsilon profiles, instead of using values from closed-form equations. When enabled, the coefficients are obtained by FFT. + DiscretizationResolution + (integer) This option only has an effect when ``DiscretizedEpsilon`` or ``SubpixelSmoothing`` are used. + This function sets the resolution of the FFT grid and vector field generated by ``PolarizationDecomposition``. + The resolution is multiplied by the largest G-vector extent (integer lattice coordinate), and should be at least 2 to satisfy the Nyquist limit. It is best to use a number with small integer factors in order for the FFT to be computed efficiently. The size of each dimension of the FFT is obviously proportional to this value. The default is 8. + See the :ref:`fmm-formulations-label` for details. + PolarizationDecomposition + (boolean) Enables or disables the use of proper in-plane Fourier factorization rules by decomposing fields into a polarization basis which conforms to the material boundaries. + The polarization basis field is generated automatically by computing a quasi-harmonic vector field everywhere tangent to the layer pattern boundaries. + This option is not guaranteed to work in the presence of tensor dielectric constants. + Enabling this feature typically improves convergence with respect to the number of G-vectors. + See the :ref:`fmm-formulations-label` for details. + PolarizationBasis + (string) Sets the method by which the polarization decomposition basis is generated. + This option only has an effect when ``PolarizationDecomposition`` is set. + See the :ref:`fmm-formulations-label` for details. + Valid choices are: + + Default + Uses a smooth tangent vector field with respect to layer patterning. + Normal + Uses a unit normal vector field with respect to layer patterning. + Jones + Uses a complex-valued Jones polarization vector field. + + LanczosSmoothing + (boolean or dict) A boolean value enables or disables smoothing of the Fourier series representations of the layer dielectric constants using the Lanczos sigma factor (box filtering). This reduces the Gibbs phenomenon ringing in the real space reconstruction. + Otherwise, specify a dictionary with keys ``Power`` (positive integer) and/or ``Width`` (positive number) to change the properties of the smoothing function. + SubpixelSmoothing + (boolean) Enables or disables the use of second-order accurate epsilon averaging rules within a pixel. + The average epsilon within a pixel is computed using the fill factor of each material and the interface direction. + Enabling this feature may improve convergence with respect to the number of G-vectors. + See the :ref:`fmm-formulations-label` for details. + ConserveMemory + (boolean) Setting this option will prevent storage of certain intermediate results. This will save approximately 30% memory for non-trivial layers. + The drawback is slower computation of any output quantities that require solutions. + + Return values: + + None. + +Miscellaneous +^^^^^^^^^^^^^ + +.. method:: Simulation.Clone() + + Duplicates an existing `Simulation object`_, copying all materials, layers, and excitation information. + No partial solution information is copied. + + Usage:: + + S2 = S.Clone() + + Arguments: + + None. + + Return values: + + A copy of the `Simulation object`_. + + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_sources/tutorial.txt b/doc/build/html/_sources/tutorial.txt new file mode 100644 index 0000000..f169d2f --- /dev/null +++ b/doc/build/html/_sources/tutorial.txt @@ -0,0 +1,122 @@ +Tutorial +======== + +Basic Usage +----------- + +This section assumes that the Lua frontend is used. +The program may be run with a Lua script as an argument, in which case the script is run and then the program terminates, or without an argument, in which case it enters interactive mode with a Lua shell. + +The basic flow of a script is listed below. +To find more information about these functions and for a full listing, see the :ref:`lua-api-label`. + +#. Obtain a new simulation object:: + + S = S4.NewSimulation() + + S now contains a simulation object with a blank specification, and no solutions. + +#. Set the lattice and number of basis functions:: + + S:SetLattice({ux,uy}, {vx,vy}) + S:SetNumG(100) + + This sets the periodicity based on the lattice vectors (ux,uy) and (vx,vy). + The number of basis functions is set to 100. + +#. Define all materials:: + + S:AddMaterial('Vacuum', 1) + S:AddMaterial('Silicon', {12, 0.01}) + + This adds a material called "Vacuum" with a dielectric constant of 1, and a material called "Silicon", with a dielectric constant of 12+0.01i. + +#. Add all layers:: + + S:AddLayer('top', 0, 'Vacuum') + S:AddLayer('slab', 0.5, 'Silicon') + S:AddLayerCopy('bottom', 0, 'top') + + Here we are adding a semi-infinite Vacuum layer (the thickness is largely irrelevant), a middle slab layer made of silicon with a thickness of 0.5, and finally a bottom semi-infinite layer that is a copy of the top layer. + It is always preferable to copy layers if possible since it reduces the computational cost. + +#. Add patterning to layers:: + + S:SetLayerPatternCircle('slab', -- layer to pattern + 'Vacuum', -- material inside circle + {0,0}, -- center of circle + 0.2) -- radius of circle + +#. Specify the excitation mechanism:: + + S:SetExcitationPlanewave( + {0, 0}, -- phi in [0,180), theta in [0,360) + {1, 0}, -- s-polarization amplitude and phase in degrees + {0, 0}) -- p-polarization + + This sets the excitation to a normally incident planewave with amplitude 1. + +#. Specify the operating frequency:: + + S:SetFrequency(0.4) + +#. Obtain desired output:: + + transmission = S:GetPowerFlux('bottom') + print(transmission) + + This obtains the forward power flux in the bottom layer, which is also the transmitted power. + +.. _fmm-formulations-label: + +Fourier Modal Method formulations +--------------------------------- + +There has been extensive literature on the best way to generate the Fourier series coefficients for the in-plane dielectric profiles of each layer. S4 implements a number of different formulations. The following functions determine which formulation is selected: + +* UseDiscretizedEpsilon +* UsePolarizationDecomposition +* UseSubpixelSmoothing +* UseJonesVectorBasis +* UseNormalVectorBasis + +In addition, the following functions control accuracy and the lattice truncation: + +* SetResolution +* SetLatticeTruncation + +To simplify the choice for users, the table below summarizes the recommended settings. It is recommended to always use circular truncation unless there is a good reason to do otherwise. Speed indicates the speed of the Fourier coefficient generation, which is usually not the dominant part of the simulation time. + ++-----------------+-------------------------+------------------------+--------+----------+ +| Options | Can handle Anisotropic? | Recommended resolution | Speed | Accuracy | ++=================+=========================+========================+========+==========+ +| none | yes | N/A | fast | poor | ++-----------------+-------------------------+------------------------+--------+----------+ +| Disc | yes | 8 | medium | poor | ++-----------------+-------------------------+------------------------+--------+----------+ +| Subpixel | yes | 4 | medium | medium | ++-----------------+-------------------------+------------------------+--------+----------+ +| Pol | no | 8 | slow | good | ++-----------------+-------------------------+------------------------+--------+----------+ +| Pol+Normal | no | 8 | slow | good | ++-----------------+-------------------------+------------------------+--------+----------+ +| Pol+Jones | no | 8 | slow | good | ++-----------------+-------------------------+------------------------+--------+----------+ +| Disc+Pol | no [#f1]_ | 4 | slow | medium | ++-----------------+-------------------------+------------------------+--------+----------+ +| Disc+Pol+Normal | no [#f1]_ | 4 | slow | medium | ++-----------------+-------------------------+------------------------+--------+----------+ +| Disc+Pol+Jones | no [#f1]_ | 4 | slow | medium | ++-----------------+-------------------------+------------------------+--------+----------+ + +.. rubric:: Footnotes + +.. [#f1] The formulation does not strictly work correctly for anisotropic media however it may still work. Proper support for anisotropic materials is in principle possible. There are currently no plans for implementing generation of the proper basis fields for this feature. + +Examples +-------- + +The source distribution of S4 includes numerous fully working didactic examples as well as examples replicating published results. +You can find these examples in the ``examples/`` directory of the source distribution. + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_sources/units.txt b/doc/build/html/_sources/units.txt new file mode 100644 index 0000000..b63cee8 --- /dev/null +++ b/doc/build/html/_sources/units.txt @@ -0,0 +1,31 @@ +Units & Coordinates +=================== + +|S4| solves the linear Maxwell's equations, which are scale-invariant. +Therefore, |S4| uses normalized units, so the conversion between the numbers in |S4| and physically relevant numbers can sometimes be confusing. +Here we show how to perform these conversions and provide some examples. + +Length, time, and frequency +--------------------------- + +The speed of light and the vacuum permittivity and vacuum permeability are all normalized to unity in |S4|. +Because of this, time is measured in units of length and frequency is measured in units of inverse length. +Due to the scale invariant nature of the linear Maxwell's equations, there is no intrinsic length unit. +Instead, one can imagine that all lengths specified in |S4| are multiples of a common reference length unit. + +When the lattice vectors are set, this determines a length scale. +Suppose we have a square lattice with a periodicity of 680nm. It might be logical then to choose 1 micron as the base length unit, and to specify all lengths in microns. The lattice would then be set to the vectors (0.68, 0) and (0, 0.68). +Since frequency is in units of inverse length, then ``SetFrequency(1)`` corresponds to a wavelength of 680nm or a physical frequency of (c/680nm) = 441 THz, and ``SetFrequency(1.1)`` corresponds to a wavelength of (680/1.1) = 618nm, etc. + +Amplitudes and powers +--------------------- + +Typically |S4| is used to compute transmission or reflection spectra, so the absolute units of incident power or amplitude are irrelevant. However, sometimes, it is necessary to be able to translate these figures into physical units. + +Under a normally-incident planewave excitation, the incident power is 1 if the amplitude is 1, regardless of unit cell size. +At off-normal incidence, the incident power is reduced by a factor of cos(phi), where phi is the polar angle (angle from normal incidence). + +The specified amplitudes are for the electric field. +If the incident power is considered to have units of Watts per unit-cell-area, then the electric field has units of Volts per square-root-of-unit-cell-area. + +.. |S4| replace:: S\ :sup:`4` diff --git a/doc/build/html/_static/ajax-loader.gif b/doc/build/html/_static/ajax-loader.gif new file mode 100644 index 0000000..61faf8c Binary files /dev/null and b/doc/build/html/_static/ajax-loader.gif differ diff --git a/doc/build/html/_static/basic.css b/doc/build/html/_static/basic.css new file mode 100644 index 0000000..d8e0346 --- /dev/null +++ b/doc/build/html/_static/basic.css @@ -0,0 +1,536 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + width: 170px; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + width: 30px; +} + +img { + border: 0; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.optional { + font-size: 1.3em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +tt.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +tt.descclassname { + background-color: transparent; +} + +tt.xref, a tt { + background-color: transparent; + font-weight: bold; +} + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/doc/build/html/_static/comment-bright.png b/doc/build/html/_static/comment-bright.png new file mode 100644 index 0000000..551517b Binary files /dev/null and b/doc/build/html/_static/comment-bright.png differ diff --git a/doc/build/html/_static/comment-close.png b/doc/build/html/_static/comment-close.png new file mode 100644 index 0000000..09b54be Binary files /dev/null and b/doc/build/html/_static/comment-close.png differ diff --git a/doc/build/html/_static/comment.png b/doc/build/html/_static/comment.png new file mode 100644 index 0000000..92feb52 Binary files /dev/null and b/doc/build/html/_static/comment.png differ diff --git a/doc/build/html/_static/default.css b/doc/build/html/_static/default.css new file mode 100644 index 0000000..e85f896 --- /dev/null +++ b/doc/build/html/_static/default.css @@ -0,0 +1,273 @@ +/* + * default.css_t + * ~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- default theme. + * + * :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: sans-serif; + font-size: 100%; + background-color: #ddd; + color: #000; + margin: 0; + padding: 0; +} + +div.document { + background-color: #ddd; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 230px; +} + +div.body { + background-color: #fff; + color: #000; + padding: 0 20px 30px 20px; +} + +div.footer { + color: #333; + width: 100%; + padding: 9px 0 9px 0; + text-align: center; + font-size: 75%; +} + +div.footer a { + color: #333; + text-decoration: underline; +} + +div.related { + background-color: #666; + line-height: 30px; + color: #ffffff; +} + +div.related a { + color: #ffffff; +} + +div.sphinxsidebar { + top: 30px; + bottom: 0; + margin: 0; + position: fixed; + overflow: auto; + height: auto; +} +/* this is nice, but it it leads to hidden headings when jumping + to an anchor */ +/* +div.related { + position: fixed; +} + +div.documentwrapper { + margin-top: 30px; +} +*/ + +div.sphinxsidebar h3 { + font-family: 'Trebuchet MS', sans-serif; + color: #333; + font-size: 1.4em; + font-weight: normal; + margin: 0; + padding: 0; +} + +div.sphinxsidebar h3 a { + color: #333; +} + +div.sphinxsidebar h4 { + font-family: 'Trebuchet MS', sans-serif; + color: #333; + font-size: 1.3em; + font-weight: normal; + margin: 5px 0 0 0; + padding: 0; +} + +div.sphinxsidebar p { + color: #333; +} + +div.sphinxsidebar p.topless { + margin: 5px 10px 10px 10px; +} + +div.sphinxsidebar ul { + margin: 10px; + padding: 0; + color: #333; +} + +div.sphinxsidebar a { + color: #33d; +} + +div.sphinxsidebar input { + border: 1px solid #33d; + font-family: sans-serif; + font-size: 1em; +} + + + +/* -- hyperlink styles ------------------------------------------------------ */ + +a { + color: #355f7c; + text-decoration: none; +} + +a:visited { + color: #355f7c; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + + + +/* -- body styles ----------------------------------------------------------- */ + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Trebuchet MS', sans-serif; + background-color: #f2f2f2; + font-weight: normal; + color: #20435c; + border-bottom: 1px solid #ccc; + margin: 20px -20px 10px -20px; + padding: 3px 0 3px 10px; +} + +div.body h1 { margin-top: 0; font-size: 200%; } +div.body h2 { font-size: 160%; } +div.body h3 { font-size: 140%; } +div.body h4 { font-size: 120%; } +div.body h5 { font-size: 110%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #c60f0f; + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + background-color: #c60f0f; + color: white; +} + +div.body p, div.body dd, div.body li { + text-align: justify; + line-height: 130%; +} + +div.admonition p.admonition-title + p { + display: inline; +} + +div.admonition p { + margin-bottom: 5px; +} + +div.admonition pre { + margin-bottom: 5px; +} + +div.admonition ul, div.admonition ol { + margin-bottom: 5px; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre { + padding: 5px; + background-color: #eeffcc; + color: #333333; + line-height: 120%; + border: 1px solid #ac9; + border-left: none; + border-right: none; +} + +tt { + background-color: #ecf0f3; + padding: 0 1px 0 1px; + font-size: 0.95em; +} + +th { + background-color: #ede; +} + +.warning tt { + background: #efc2c2; +} + +.note tt { + background: #d6d6d6; +} + +.viewcode-back { + font-family: sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} \ No newline at end of file diff --git a/doc/build/html/_static/doctools.js b/doc/build/html/_static/doctools.js new file mode 100644 index 0000000..8614442 --- /dev/null +++ b/doc/build/html/_static/doctools.js @@ -0,0 +1,235 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s == 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node) { + if (node.nodeType == 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this); + }); + } + } + return this.each(function() { + highlight(this); + }); +}; + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated == 'undefined') + return string; + return (typeof translated == 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated == 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) == 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this == '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/doc/build/html/_static/down-pressed.png b/doc/build/html/_static/down-pressed.png new file mode 100644 index 0000000..6f7ad78 Binary files /dev/null and b/doc/build/html/_static/down-pressed.png differ diff --git a/doc/build/html/_static/down.png b/doc/build/html/_static/down.png new file mode 100644 index 0000000..3003a88 Binary files /dev/null and b/doc/build/html/_static/down.png differ diff --git a/doc/build/html/_static/file.png b/doc/build/html/_static/file.png new file mode 100644 index 0000000..d18082e Binary files /dev/null and b/doc/build/html/_static/file.png differ diff --git a/doc/build/html/_static/jquery.js b/doc/build/html/_static/jquery.js new file mode 100644 index 0000000..1258119 --- /dev/null +++ b/doc/build/html/_static/jquery.js @@ -0,0 +1,9404 @@ +/*! + * jQuery JavaScript Library v1.7.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Aug 1 23:20:30 BRT 2013 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.7.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, pass ) { + var exec, + bulk = key == null, + i = 0, + length = elems.length; + + // Sets many values + if ( key && typeof key === "object" ) { + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); + } + chainable = 1; + + // Sets one value + } else if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = pass === undefined && jQuery.isFunction( value ); + + if ( bulk ) { + // Bulk operations only iterate when executing function values + if ( exec ) { + exec = fn; + fn = function( elem, key, value ) { + return exec.call( jQuery( elem ), value ); + }; + + // Otherwise they run against the entire set + } else { + fn.call( elems, value ); + fn = null; + } + } + + if ( fn ) { + for (; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + } + + chainable = 1; + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + fired = true; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + pixelMargin: true + }; + + // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead + jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat"); + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for ( i in { + submit: 1, + change: 1, + focusin: 1 + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight, + paddingMarginBorderVisibility, paddingMarginBorder, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + paddingMarginBorder = "padding:0;margin:0;border:"; + positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;"; + paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;"; + style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;"; + html = "
" + + "" + + "
"; + + container = document.createElement("div"); + container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "
t
"; + tds = div.getElementsByTagName( "td" ); + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( window.getComputedStyle ) { + div.innerHTML = ""; + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.innerHTML = ""; + div.style.width = div.style.padding = "1px"; + div.style.border = 0; + div.style.overflow = "hidden"; + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = "block"; + div.style.overflow = "visible"; + div.innerHTML = "
"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + } + + div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + if ( window.getComputedStyle ) { + div.style.marginTop = "1%"; + support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%"; + } + + if ( typeof container.style.zoom !== "undefined" ) { + container.style.zoom = 1; + } + + body.removeChild( container ); + marginDiv = div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, part, attr, name, l, + elem = this[0], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attr = elem.attributes; + for ( l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split( ".", 2 ); + parts[1] = parts[1] ? "." + parts[1] : ""; + part = parts[1] + "!"; + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + data = this.triggerHandler( "getData" + part, [ parts[0] ] ); + + // Try to fetch any internally stored data first + if ( data === undefined && elem ) { + data = jQuery.data( elem, key ); + data = dataAttr( elem, key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } + + parts[1] = value; + this.each(function() { + var self = jQuery( this ); + + self.triggerHandler( "setData" + part, parts ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + part, parts ); + }); + }, null, value, arguments.length > 1, null, false ); + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery._data( elem, deferDataKey ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery._data( elem, queueDataKey ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise( object ); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, i, max, option, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, l, isBool, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + isBool = rboolean.test( name ); + + // See #9699 for explanation of this approach (setting first, then removal) + // Do not do this for boolean attributes (see #10870) + if ( !isBool ) { + jQuery.attr( elem, name, "" ); + } + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( isBool && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true, + coords: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = "" + value ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); + + + + +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /(?:^|\s)hover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: selector && quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + special = jQuery.event.special[ event.type ] || {}, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers that should run if there are delegated events + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + + // Don't process events on disabled elements (#6911, #8165) + if ( cur.disabled !== true ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { // && selector != null + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context, seed ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set, seed ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + filter = Expr.filter[ type ]; + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + pass = not ^ found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var first, last, + doneName, parent, cache, + count, diff, + type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Sizzle.attr ? + Sizzle.attr( elem, name ) : + Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + !type && Sizzle.attr ? + result != null : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} +// Expose origPOS +// "global" as in regardless of relation to brackets/parens +Expr.match.globalPOS = origPOS; + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context, seed ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.globalPOS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /]", "i"), + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /\/(java|ecma)script/i, + rcleanScript = /^\s*", "" ], + legend: [ 1, "
", "
" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + col: [ 2, "", "
" ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + + + + + + + + +
+
+
+
+ +
+

Changelog

+
+
2013-12-31
+
Added new Python extension frontend.
+
2013-12-26
+
Added ability to efficiently output fields on a regular grid of points using an FFT.
+
2013-12-25
+
Fixed incorrect output of z-components of E-fields (incorrect application Epsilon_inv).
+
2013-10-31
+
Added optional order parameter to SetExcitationPlanewave.
+
2013-10-16
+
Layer integrals now also return imaginary parts.
+
2013-08-15
+
Fixed bug with SetLatticeTruncation not having an effect.
+
2013-05-29
+
Added additional options to Lanczos smoothing. Upgraded support to Lua 5.2 (dropped support for 5.1).
+
2013-03-30
+
Added GetLayerZIntegral to return line integrals (thanks to Ken Wang for the feature request). Changed the return convention for GetAmplitudes, and added documentation for both functions.
+
2013-03-21
+
Added GetAmplitudes to return the raw amplitudes for phase retrieval (thanks to Olivier Gauthier-Lafaye for the feature request).
+
2013-02-19
+
pattern.c now detects 1D patterns and special cases them. Eigensolver performs workspace query for greater efficiency, and Fortran interfaces tidied up. Lanczos smoothing is now an option in FFT and PolBasisVL. Added SetLayerThickness to change only thickness and not affect the cached eigenmodes.
+
2011-11-21
+
Fixed bug with rotation and translation in OutputPatternDescription (thanks Aaswath).
+
2011-09-16
+
Eigenvector basis for uniform layers not stored (identity matrix). Added option UseLessMemory to not store kp (k-cross) matrices.
+
2011-09-06
+
Fixed minor bugs and passes Valgrind without problems (for a few test runs).
+
2011-08-31
+
Added GetDiffractionOrder().
+
2011-08-30
+
Fixed normal-vector bug, resolving convergence issues with subpixel-smoothing and rectangular shapes.
+
2011-08-25
+
Added CHOLMOD direct solver to pattern.c.
+
2011-08-23
+
Fixed segment-segment intersection code. Several cases of incorrect dielectric discretization have been fixed. +Changed Enable/Disable* functions to Use*.
+
2011-06-20
+
Added MPI support. Compile with HAVE_MPI. S4.MPIRank and MPISize are available regardless of MPI support.
+
2011-04-22
+
Halved the Lanczos filter spatial width. This seems to improve convergence. +Changed default resolution to 8 from 64.
+
2011-04-21
+
Added Kottke’s subpixel smoothing method. Disabled by default. +SetLattice can now take a single number for 1D periodicity. +SpectrumSampler can now be parallelized.
+
2011-04-20
+
Changed PolarizationBasisOversamplingFactor to Resolution.
+
2011-04-18
+
Fixed crash when using Kiss FFT. I overzealously converted free to S4_free for kiss_fft.
+
2011-03-27
+
Switched numerical memory allocation to 16-byte alignment. LinearSolve’s now use LAPACK blocked code. Fixed some memory leaks with S4_Simulation objects (field cache was not being freed).
+
2011-03-20
+
Added Integrate function.
+
2010-10-28
+
Fixed nan output due to uninitialized matrices Ml, Mlp1, Bl, Blp1 in rcwa.cpp.
+
2010-09-10
+
Fixed incorrect output of z-components of E- and H-fields (missing in-plane k-vector dependent phase).
+
2010-08-23
+
Fixed memory leak in S4_DestroySolution; kx and Bands and Solution structures were not freed.
+
2010-08-10
+
Fixed erroneous generation of values for Fourier transform for non-tensor materials in the context of a with-tensor stack. +Added S4.ConvertUnits.
+
2010-08-09
+
Fixed a bug with S-Matrix generation between two identical layers (previous results were incorrect).
+
2010-08-05
+
Added anisotropic material support (currently incompatible with polarization basis, but without warning). Added cubic hermite spline interpolation.
+
2010-08-04
+
Added real material data for metals.
+
2010-08-03
+
Traced a problem with incorrect multithreaded results back to LAPACK. It is critical that LAPACK not use static allocation for local arrays (fixed with -frecursive).
+
2010-07-29
+
Fixed 1D lattice G selection (even numbers would cause duplicates)
+
2010-07-28
+
Fixed planewave excitation calculations for off-normal incidence. Previous s- and p-polarizations were mixed up and wrong. Added command line switches a and t.
+
2010-07-26
+
Fixed circular truncation code; was dropping certain orders (2,2 on a square lattice).
+
2010-07-24
+
Fixed polygon patterning (incorrect Fourier transform formulation).
+
2010-07-23
+
Added ability to output diffraction efficiency, obtain the G-vector list, and fixed the Fourier transforms for non-unit area unit cells.
+
2010-07-22
+
Added caching of polarization basis vector field Fourier transform matrices. +Repeated computation of the same structure at different frequencies or k-vectors is much faster now that the vector field does not need to be recreated each time.
+
2010-07-21
+
Initial announcement of S4. Supports multithreading.
+
+
+ + +
+
+
+
+
+ +

Table Of Contents

+ + +

Previous topic

+

Frequently Asked Questions

+

Next topic

+

Developer Info

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/citing.html b/doc/build/html/citing.html new file mode 100644 index 0000000..609e24b --- /dev/null +++ b/doc/build/html/citing.html @@ -0,0 +1,156 @@ + + + + + + + + How to cite — S4 1.1 documentation + + + + + + + + + + + + + + +
+
+
+
+ +
+

How to cite

+

We kindly ask that you reference the S4 package and its authors in any publication for which you used it. +This is obviously neither legally binding nor enforceable, but we hope that you do.

+

The preferred citation for S4 is the following paper:

+
+
+
Victor Liu and Shanhui Fan, “S4: A free electromagnetic solver for layered periodic structures,” Computer Physics Communications 183, 2233-2244 (2012)
+
http://dx.doi.org/10.1016/j.cpc.2012.04.026
+
+
+

Or, in BibTeX format:

+
@article{Liu20122233,
+        author = "Victor Liu and Shanhui Fan",
+        title = "S$^4$ : A free electromagnetic solver for layered periodic structures",
+        journal = "Computer Physics Communications",
+        volume = "183",
+        number = "10",
+        pages = "2233 - 2244",
+        year = "2012",
+        issn = "0010-4655",
+        doi = "10.1016/j.cpc.2012.04.026",
+        url = "http://www.sciencedirect.com/science/article/pii/S0010465512001658",
+}
+
+

It is not absolutely necessary for the “4” in S4 to be a superscript, but it is more correct if it is. +A brief description of the algorithm might be:

+
+
The transmission spectrum was computed using the Fourier Modal Method using a freely available software package [ref].
+
+ + +
+
+
+
+
+ +

Table Of Contents

+ + +

Previous topic

+

License and Copyright

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/dev_info.html b/doc/build/html/dev_info.html new file mode 100644 index 0000000..225129e --- /dev/null +++ b/doc/build/html/dev_info.html @@ -0,0 +1,238 @@ + + + + + + + + Developer Info — S4 1.1 documentation + + + + + + + + + + + + + + + +
+
+
+
+ +
+

Developer Info

+
+

Dependencies

+
    +
  • Lua 5.2.x, both headers and libraries.
  • +
  • Python 2 or 3, both headers and libraries.
  • +
  • BLAS, or equivalent, library only.
  • +
  • LAPACK (optional, 3.2 or later), library only.
  • +
  • Pthreads (optional), both headers and libraries.
  • +
  • FFTW3 (optional, 3.x), both headers and libraries.
  • +
  • CHOLMOD (optional), both headers and libraries.
  • +
+
+

BLAS

+

The performance of S4 is directly dependent on the performance of the BLAS library that it is linked against. Without a BLAS library, the default RNP routines are used, which are suboptimal. It is recommended that either vendor specific routines (Intel MKL or AMD AMCL) are used, or tuned libraries such as ATLAS or OpenBLAS are used. Vendor specific routines have incompatible calling/naming conventions than the standard Fortran interface, so some porting effort is required. Note that OpenBLAS should be compiled without threading if threading is enabled within S4; otherwise results may not be correct. Installing these packages from official distribution repositories is almost always a bad idea, since the code must be tuned to the particular machine it will run on.

+
+
+

LAPACK

+

If a precompiled LAPACK library is used, ensure ZGEEV is thread safe for large matrices. Specifically, bug0061 in the LAPACK errata means that the maximum stack space reserved by the Fortran compiler used to build LAPACK must be sufficient to hold certain temporaries on the stack instead of in static (shared) memory. The best way to avoid this with GFortran is to use the -frecursive flag. A simple test of thread safety is provided in the testing/Lapackthreadtest/ directory.

+

If no LAPACK library is available, the default RNP routines are used, which are suboptimal due to lack of blocked routines. However, they are definitely thread-safe.

+
+
+

CHOLMOD

+

Although not required, it is recommended when polarization decomposition settings are enabled, since without it, a conjugate gradient solver is used instead. The conjugate gradient solver does not always converge for fine discretizations.

+
+
+

FFTW

+

This library is optional; the Kiss FFT library is used instead when FFTW is not present. When available the version must be 3.x. This does not have a great effect on simulation speed since the FFT is required only a handful of times, and tends to be rather small in problem size.

+
+
+
+

Porting

+

The code is developed in Windows under MinGW+MSYS and runs primarily in UNIX-like environments. For other platforms, the following list details the main problem areas.

+
+
In main.c near the top dealing with threads (this is not a problem if Pthreads are disabled). +In pattern/predicates.c, the settings may need modification to enable robust computations. +In numalloc.c, a more efficient aligned allocator may be supplied instead of the default.
+
+
+

Program structure

+

S4 is built as a library on top of the Lua programming language, or as a Python extension.

+

S4 has 3 main layers:

+
+
main_lua.c
+
Specifies the Lua interface, which passes arguments on to the S4 layer.
+
S4.cpp
+
The glue between the user specified information and the RCWA specification. The heavy lifting here is mainly determining which Fourier orders to use, and generating the Fourier dielectric matrices. The header S4.h is C-compatible and allows binding of a custom interface to the internals, or use programmatically as a component.
+
rcwa.cpp
+
The real RCWA and S-matrix algorithms are contained here. The main functions are solving the layer band structure, composing S-matrices for stacks of layers, and solving for solutions given input fields. Also contained within here are functions for manipulating solution vectors and computing various quantities of interest.
+
+
+

Auxilliary functions

+
+
pattern.c/intersection.c
+
A self-contained library for representing layer patterning, as well as generating proper discretizations, Fourier transforms of the patterns, and quasiharmonic conformal flow fields. fmm +A set of different formulations to generate the Fourier components of the dielectric function. kiss_fft +A simple FFT library for performing numerical Fourier transforms of the conformal vector fields. RNP +A library of numerical linear algebra functions, and a thin layer over the BLAS and LAPACK libraries.
+
SpectrumSampler/Interpolator
+
These are addtional convenience modules to perform commonly needed tasks.
+
+
+
+
+

Areas of improvement

+
    +
  • Symmetry detection. Hermitian or symmetric eigenproblems are not detected and specialized currently.
  • +
  • Bandsolving. 3D layered structure bandsolving can be implemented relatively straightforwardly.
  • +
  • Robustness and efficiency of G-vector selection. The current implementation is likely unnecessarily slow. Robustness of the algorithm for a very wide variety of lattices remains to be investigated.
  • +
  • Conjugate Gradient implementation in pattern.c. The current CG implementation is a textbook implementation, with hard coded regularization.
  • +
  • Workspace pre-allocation for repeated calls. Currently, many workspace parameters in rcwa.cpp are ignored, defaulting to automatic allocation. For repeated small calls, the allocation overhead may be substantial. Profiling is needed.
  • +
  • A full programming API in S4.h. The current Lua interface reaches into the Simulation structure for certain functions. It is best to hide the details of the Simulation structure behind an opaque pointer and fix an API.
  • +
  • Parallelization over layer band structure computations. For a large number of non-trivial layers, a rather simple parallelization would be to compute the bands of the layers in parallel. It is unclear whether this requires an invasive modification of S4.cpp.
  • +
  • Parallelization over S-matrix assembly. The construction of the S-matrix should be parallelizable by a divide-and-conquer algorithm. Furthermore, it ought to be possible to cache intermediate results to speed up computing many S-matrices.
  • +
  • Graceful handling of diffraction threshold frequencies. If a frequency happens to cause a zero eigenvalue in a layer’s band structure, some internal matrices become singular, and no solution is obtainable. This requires a thorough theoretical investigation.
  • +
+
+
+

Coding conventions

+

The code is mostly C-styled C++. The need to use C++ is mainly for the complex number type. There should never be non-trivial objects (only Plain Old Data structs), and certainly no inheritance, polymorphism, or templates (except in RNP).

+

Indentation should be 4 spaces per tab. Always use tabs instead of spaces. The actual tab width should never matter for readability, meaning tabs can only exist contiguously starting from the left-most column, and comment blocks should never sit at the end of lines of code. Lines should be kept to around 72 or 80 characters in length if possible, especially for comment blocks.

+

Functions generally are in Lapack-style, where there are a large number of well defined inputs, and a number of outputs returned by pointers. Functions return an integer code, with negative values corresponding to invalid parameters. When appropriate, workspaces can be passed in to reduce the number of dynamic allocations. Also, when convenient, workspace querying should be supported.

+

The code should compile cleanly with all warnings enabled. The only exemptions are external libraries like Kiss FFT or the geometric predicates sources.

+
+
+ + +
+
+
+
+
+ +

Table Of Contents

+ + +

Previous topic

+

Changelog

+

Next topic

+

License and Copyright

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/faq.html b/doc/build/html/faq.html new file mode 100644 index 0000000..96fc6fe --- /dev/null +++ b/doc/build/html/faq.html @@ -0,0 +1,176 @@ + + + + + + + + Frequently Asked Questions — S4 1.1 documentation + + + + + + + + + + + + + + + +
+
+
+
+ +
+

Frequently Asked Questions

+
    +
  • Where is the unit cell located and do I need to define periodic copies of patterns?

    +
    +

    This a tricky topic. +If you use an FMM formuation which is based on analytic Fourier transforms (which includes the default settings), then all patterns are automatically periodized, and in some sense, the shape and location of the unit cell is irrelevant. +For spatially sampled FMM formulations (those that rely on an FFT), the unit cell is the Wigner-Seitz cell centered at the origin. +For these formulations you need to specify periodic copies. +You should always check that the patterning is specified correctly using GetEpsilon() or OutputLayerPatternRealization().

    +
    +
  • +
  • What happens if I try to compute a quantity “outside” the structure?

    +
    +

    For example, if you specify a negative z coordinate, that corresponds to being within the first layer, since it is assumed the first layer extends infinitely towards negative infinity in the z direction. +Similarly, if you specify a z coordinate past the total thickness of all layers, it is within the last layer. +This is why you can specify zero thickness for the first and last layers. +However, it is recommended that you increase the thickness of the first and last layers sufficiently so that you don’t need to compute quantities “outside” the specified structure since field quantities may suffer from numerical instability in those cases.

    +
    +
  • +
  • How do I specify frequency dependent material parameters?

    +
    +

    If you have a loop iterating over frequencies, then within the loop simply set new epsilon values for the materials. +In order to incorporate values from tabulated data, you can use the Interpolator object and pass it a table of values. +Large tables can be defined in separate files and included using the Lua dofile() function.

    +
    +
  • +
  • Why is the POVRay output wrong?

    +
    +

    The POVRay feature is only to provide a starting point for writing an actual POVRay script. +It is not guaranteed to be correct. You should not rely on this feature.

    +
    +
  • +
  • Should the 4 in S4 be superscripted in publications?

    +
    +

    Although we would prefer that it be superscripted, it does not have to be. The preferred way to typeset it in LaTeX is: S$^4$.

    +
    +
  • +
+
+ + +
+
+
+
+
+ +

Table Of Contents

+ + +

Previous topic

+

Units & Coordinates

+

Next topic

+

Changelog

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/genindex.html b/doc/build/html/genindex.html new file mode 100644 index 0000000..a0fc0dc --- /dev/null +++ b/doc/build/html/genindex.html @@ -0,0 +1,580 @@ + + + + + + + + + Index — S4 1.1 documentation + + + + + + + + + + + + + +
+
+
+
+ + +

Index

+ +
+ A + | C + | G + | I + | M + | N + | O + | R + | S + +
+

A

+ + + +
+ +
AddLayer() (S4.Simulation method) +
+ + +
AddLayerCopy() (S4.Simulation method) +
+ +
+ +
arg (in module S4) +
+ +
+ +

C

+ + + +
+ +
Clone() (S4.Simulation method) +
+ +
+ +
ConvertUnits() (in module S4) +
+ +
+ +

G

+ + + +
+ +
GetAmplitudes() (S4.Simulation method) +
+ + +
GetBasisSet() (S4.Simulation method) +
+ + +
GetEpsilon() (S4.Simulation method) +
+ + +
GetFields() (S4.Simulation method) +
+ + +
GetFieldsOnGrid() (S4.Simulation method) +
+ +
+ +
GetLayerVolumeIntegral() (S4.Simulation method) +
+ + +
GetPowerFlux() (S4.Simulation method) +
+ + +
GetPowerFluxByOrder() (S4.Simulation method) +
+ + +
GetReciprocalLattice() (S4.Simulation method) +
+ + +
GetSMatrixDeterminant() (S4.Simulation method) +
+ +
+ +

I

+ + + +
+ +
Integrate() (in module S4) +
+ + +
Interpolator (class in S4) +
+ +
+ +
Interpolator:Get() (in module S4) +
+ +
+ +

M

+ + + +
+ +
MPIRank (in module S4) +
+ +
+ +
MPISize (in module S4) +
+ +
+ +

N

+ + + +
+ +
New() (in module S4) +
+ + +
NewInterpolator() (in module S4) +
+ +
+ +
NewSimulation() (in module S4) +
+ + +
NewSpectrumSampler() (in module S4) +
+ +
+ +

O

+ + + +
+ +
OutputLayerPatternPostscript() (S4.Simulation method) +
+ +
+ +
OutputStructurePOVRay() (S4.Simulation method) +
+ +
+ +

R

+ + +
+ +
RemoveLayerRegions() (S4.Simulation method) +
+ +
+ +

S

+ + + +
+ +
S4 (module), [1] +
+ + +
SetExcitationPlanewave() (S4.Simulation method) +
+ + +
SetFrequency() (S4.Simulation method) +
+ + +
SetLayerThickness() (S4.Simulation method) +
+ + +
SetMaterial() (S4.Simulation method) +
+ + +
SetOptions() (S4.Simulation method) +
+ + +
SetRegionCircle() (S4.Simulation method) +
+ + +
SetRegionEllipse() (S4.Simulation method) +
+ + +
SetRegionPolygon() (S4.Simulation method) +
+ + +
SetRegionRectangle() (S4.Simulation method) +
+ + +
Simulation (class in S4), [1] +
+ + +
Simulation:AddLayer() (in module S4) +
+ + +
Simulation:AddLayerCopy() (in module S4) +
+ + +
Simulation:AddMaterial() (in module S4) +
+ + +
Simulation:Clone() (in module S4) +
+ + +
Simulation:GetAmplitudes() (in module S4) +
+ + +
Simulation:GetDiffractionOrder() (in module S4) +
+ + +
Simulation:GetEField() (in module S4) +
+ + +
Simulation:GetEpsilon() (in module S4) +
+ + +
Simulation:GetFieldPlane() (in module S4) +
+ + +
Simulation:GetFields() (in module S4) +
+ + +
Simulation:GetGList() (in module S4) +
+ + +
Simulation:GetHField() (in module S4) +
+ + +
Simulation:GetLayerElectricEnergyDensityIntegral() (in module S4) +
+ + +
Simulation:GetLayerElectricFieldIntensityIntegral() (in module S4) +
+ + +
Simulation:GetLayerEnergyDensityIntegral() (in module S4) +
+ + +
Simulation:GetLayerMagneticEnergyDensityIntegral() (in module S4) +
+ + +
Simulation:GetLayerZIntegral() (in module S4) +
+ + +
Simulation:GetNumG() (in module S4) +
+ + +
Simulation:GetPowerFlux() (in module S4) +
+ + +
Simulation:GetPowerFluxByOrder() (in module S4) +
+ + +
Simulation:GetReciprocalLattice() (in module S4) +
+ + +
Simulation:GetSMatrixDeterminant() (in module S4) +
+ + +
Simulation:GetStressTensorIntegral() (in module S4) +
+ +
+ +
Simulation:OutputLayerPatternDescription() (in module S4) +
+ + +
Simulation:OutputLayerPatternRealization() (in module S4) +
+ + +
Simulation:OutputStructurePOVRay() (in module S4) +
+ + +
Simulation:SetBasisFieldDumpPrefix() (in module S4) +
+ + +
Simulation:SetExcitationExterior() (in module S4) +
+ + +
Simulation:SetExcitationPlanewave() (in module S4) +
+ + +
Simulation:SetFrequency() (in module S4) +
+ + +
Simulation:SetLattice() (in module S4) +
+ + +
Simulation:SetLatticeTruncation() (in module S4) +
+ + +
Simulation:SetLayer() (in module S4) +
+ + +
Simulation:SetLayerPatternCircle() (in module S4) +
+ + +
Simulation:SetLayerPatternEllipse() (in module S4) +
+ + +
Simulation:SetLayerPatternPolygon() (in module S4) +
+ + +
Simulation:SetLayerPatternRectangle() (in module S4) +
+ + +
Simulation:SetLayerThickness() (in module S4) +
+ + +
Simulation:SetMaterial() (in module S4) +
+ + +
Simulation:SetNumG() (in module S4) +
+ + +
Simulation:SetResolution() (in module S4) +
+ + +
Simulation:SetVerbosity() (in module S4) +
+ + +
Simulation:UseDiscretizedEpsilon() (in module S4) +
+ + +
Simulation:UseJonesVectorBasis() (in module S4) +
+ + +
Simulation:UseLanczosSmoothing() (in module S4) +
+ + +
Simulation:UseLessMemory() (in module S4) +
+ + +
Simulation:UseNormalVectorBasis() (in module S4) +
+ + +
Simulation:UsePolarizationDecomposition() (in module S4) +
+ + +
Simulation:UseSubpixelSmoothing() (in module S4) +
+ + +
SolveInParallel() (in module S4) +
+ + +
SpectrumSampler (class in S4) +
+ + +
SpectrumSampler:GetFrequencies() (in module S4) +
+ + +
SpectrumSampler:GetFrequency() (in module S4) +
+ + +
SpectrumSampler:GetSpectrum() (in module S4) +
+ + +
SpectrumSampler:IsDone() (in module S4) +
+ + +
SpectrumSampler:SubmitResult() (in module S4) +
+ + +
SpectrumSampler:SubmitResults() (in module S4) +
+ +
+ + + +
+
+
+
+
+ +

Table Of Contents

+ + + + + + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/index.html b/doc/build/html/index.html new file mode 100644 index 0000000..9116dc2 --- /dev/null +++ b/doc/build/html/index.html @@ -0,0 +1,214 @@ + + + + + + + + Introduction to S4 — S4 1.1 documentation + + + + + + + + + + + + + + +
+
+
+
+ +
+

Introduction to S4

+
+

What is it?

+

S4 (or simply S4) stands for Stanford Stratified Structure Solver, a frequency domain code to solve the linear Maxwell’s equations in layered periodic structures. +Internally, it uses Rigorous Coupled Wave Analysis (RCWA; also called the Fourier Modal Method (FMM)) and the S-matrix algorithm. +The program is implemented using a Lua frontend, or alternatively, as a Python extension. +S4 was developed by Victor Liu of the Fan Group in the Stanford Electrical Engineering Department.

+_images/schem_640.png +
+
+

What can it compute?

+

S4 can compute transmission, reflection, or absorption spectra of structures composed of periodic, patterned, planar layers. +The electromagnetic fields throughout the structure can also be obtained, as well as certain line and volume integrals. +The spectra obtained from S4 are extremely smooth, making it easier for local and global optimization.

+_images/spec.png +
+ +
+

Releases

+
    +
  • Version 1.1

    +

    Latest version using Lua 5.2.x and supports Python.

    +
  • +
  • Version 1.0

    +

    This is the original version that was published in Computer Physics Communications. It requires on Lua 5.1.x and packs Python bindings.

    +
  • +
+
+
+

Indices and tables

+ +
+
+ + +
+
+
+
+
+ +

Table Of Contents

+ + +

Next topic

+

Download & Installation

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/install.html b/doc/build/html/install.html new file mode 100644 index 0000000..a32b048 --- /dev/null +++ b/doc/build/html/install.html @@ -0,0 +1,214 @@ + + + + + + + + Download & Installation — S4 1.1 documentation + + + + + + + + + + + + + + + +
+
+
+
+ +
+

Download & Installation

+

There are two choices for downloading S4: downloading a binary package from below, or cloning the GitHub respository and building from source. +The latter is the preferred method for obtaining the latest features and bug fixes.

+
+

Binary packages

+

The binary packages do not contain the examples and documentation, and are compiled with the bare minimum of features. +You need to download that separately.

+ +
+
+

GitHub repository

+

The source code is located at this GitHub repository. +You can clone it with the command:

+
git clone https://github.com/victorliu/S4.git
+
+
+
+

Compiling from source

+
+

Dependencies

+

Before compiling, there are a number of packages that are recommended. +None of these is required except for either Lua or Python.

+
    +
  • Lua 5.2.x - This is required for the Lua frontend. +Either this or Python is required. +On Ubuntu or Debian, the repository package is called liblua5.2-dev.
  • +
  • Python 2.x or 3.x - This is required to build S4 as a Python extension. +Either this or Lua is required. +On Ubuntu or Debian, the repository package is called python-dev or python3-dev.
  • +
  • BLAS and Lapack implementation - Optional, but highly recommended. It is suggested that OpenBLAS be used.
  • +
  • FFTW3 - Optional, provides a 2-3x speedup in FFT computations. +On Ubuntu or Debian, the repository package is called libfftw3-dev.
  • +
  • CHOLMOD - Optional, provides a speedup in certain FMM formulations. +On Ubuntu or Debian, install the repository package is called libsuitesparse-dev.
  • +
  • POSIX Threads - Optional, typically provided by the compiler. Allows multi-threading support on shared-memory machines.
  • +
  • MPI - Optional, provides support for parallel computing on distributed-memory machines.
  • +
+
+
+

Compilation

+

# Edit Makefile.custom and set the library flags for all the dependencies that can be provided. +# Run:

+
make lib
+
+

# Next, build either the Lua frontend:

+
      make S4lua
+
+or the Python extension::
+
+      make S4_pyext
+
+

# The resulting Lua binary is just called S4, and the Python shared object is build/lib.*/S4.so.

+
+
+
+ + +
+
+
+
+
+ +

Table Of Contents

+ + +

Previous topic

+

Introduction to S4

+

Next topic

+

Tutorial

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/license.html b/doc/build/html/license.html new file mode 100644 index 0000000..1561afa --- /dev/null +++ b/doc/build/html/license.html @@ -0,0 +1,156 @@ + + + + + + + + License and Copyright — S4 1.1 documentation + + + + + + + + + + + + + + + +
+
+
+
+ + + + +
+
+
+
+
+ +

Table Of Contents

+ + +

Previous topic

+

Developer Info

+

Next topic

+

How to cite

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/lua-modindex.html b/doc/build/html/lua-modindex.html new file mode 100644 index 0000000..8e2ccd1 --- /dev/null +++ b/doc/build/html/lua-modindex.html @@ -0,0 +1,135 @@ + + + + + + + + Lua Module Index — S4 1.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +

Lua Module Index

+ +
+ s +
+ + + + + + + +
 
+ s
+ S4 +
+ + +
+
+
+
+
+ +

Table Of Contents

+ + + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/lua_api.html b/doc/build/html/lua_api.html new file mode 100644 index 0000000..d8fe414 --- /dev/null +++ b/doc/build/html/lua_api.html @@ -0,0 +1,1816 @@ + + + + + + + + Lua API reference — S4 1.1 documentation + + + + + + + + + + + + + + + +
+
+
+
+ +
+

Lua API reference

+

S4 is built as a set of extensions to the Lua scripting language. +Usage of S4 involves writing a Lua script to call into various parts of S4. +Here we describe all of the S4 specific functions that can be called within the Lua environment.

+
+

S4 library

+

All top level functions of S4 are located in the S4 library. +These functions mainly return objects which can be manipulated to obtain desired results.

+
+
+S4.NewSimulation()
+

Returns a new blank Simulation object.

+

Usage:

+
S = S4.NewSimulation()
+
+
+

Arguments:

+
+
None.
+

Return values:

+
+
+
S
+
A new Simulation object.
+
+
+
+ +
+
+S4.NewSpectrumSampler(f_start, f_end, options)
+

Returns a new SpectrumSampler object.

+

Usage:

+
sampler = S4.NewSpectrumSampler(f_start, f_end, options)
+
+
+

Arguments:

+
+
+
f_start, f_end
+
(number) Starting and ending frequencies of the frequency range in which to sample.
+
options
+
(table) A table of options controlling the sampling behavior. The keys and expected values are described below. If any option is not specified, the default value is used. Any out-of-range values are clamped to the valid range.
+
InitialNumPoints
+
(integer) The initial number of (uniformly spaced) sample points to use. If this value is not large enough, fine features may be missed. The default is 33.
+
RangeThreshold
+
(number) The threshold below which the difference between adjacent result values will not cause an interval to be subdivided. The default is 0.001.
+
MaxBend
+
(number) The cosine of the maximum bend angle of the normalized angle between adjacent segments. +For angles larger than the maximum bend angle, one of the adjacent intervals is subdivided. +The default bend angle is 10 degrees.
+
MinimumSpacing
+
(number) The relative frequency space (relative to the sampling interval size) below which subdivision will not occur. The default is 1e-6.
+
Parallelize
+
(boolean) Allows multiple frequency points to be solved in parallel. This option affects which methods can be called for a SpectrumSampler object. The default is false.
+
+
+

Return values:

+
+
+
sampler
+
A new SpectrumSampler object.
+
+
+
+ +
+
+S4.NewInterpolator(type, table)
+

Returns a new Interpolator object.

+

Usage:

+
interpolator = S4.NewInterpolator('type', {
+  {x1, {y1_1, y1_2, ... }},
+  {x2, {y2_1, y2_2, ... }},
+  ...
+})
+
+
+

Arguments:

+
+
+
type
+

(string) Type of interpolation to use.

+
+
‘linear’
+
Performs linear interpolation (and extrapolation) between values.
+
‘cubic hermite spline’
+
Uses a cubic Hermite spline interpolation with Kochanek-Bartels tangents (really just a Catmull-Rom spline).
+
+
+
table
+
The second argument should be a table of tables. +Each subtable should have as its first element the abscissa of a data sample, and the second element should be a table of all the ordinate values. +The ordinate ordering is clearly important, and only the number of ordinate values for the first abscissa value determines the assumed number of ordinate values for the remaining abscissae.
+
+
+

Return values:

+
+
+
interpolator
+
A new Interpolator object.
+
+
+
+ +
+
+S4.SolveInParallel(layername, ...)
+

Forces the computation of a layer solution for several simulation objects in parallel. +When compiled without thread support, the computations are done serially.

+

Usage:

+
S4.SolveInParallel('layer', Sa, Sb, ...)
+
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer for which solutions should be computed. If the simulation objects do not have layer matching the provided name, then no solve is performed for that object.
+
Sa, Sb, ...
+
(Simulation object) The set of Simulation objects for which solutions are computed. It is useful to use the Clone() method to make copies.
+
+
+

Return values:

+
+
None.
+
+ +
+
+S4.ConvertUnits(value, from_units, to_units)
+

Performs unit conversions.

+

Usage:

+
S4.ConvertUnits(value, from_units, to_units)
+
+
+

Arguments:

+
+
+
value=
+
(number) The value to convert.
+
from_units, to_units
+

(string) The units in which value is currently expressed, and the desired units. +Currently supported units:

+
+
Lengths: “um”, “nm”, “m”, “cm”, “mm” +Energies: “eV”, “J” +Frequencies: “THz”, “GHz”, “Hz”, “rad/s”
+
+
+
+

Return values:

+
+
The converted value, or nil if no conversion was possible.
+
+ +
+
+S4.Integrate(func, range1, range2, ..., opts)
+

Performs adaptive numerical integration in an arbitrary number of dimensions.

+

Usage:

+
integral,error = S4.Integrate(func, range1, range2, ..., opts)
+
+
+

Arguments:

+
+
+
func
+
(function) The function to integrate. It should take a number of arguments matching the number of range parameters passed in (the number of independent variables), and return a single number.
+
range1, range2, ...
+
(table) Each table should contain two elements corresponding to lower and upper limits of integration for the corresponding variable.
+
opts
+

(table) Options to the integration routine. This table is distinguished from an integration limit range by the presence of string keys. The options are:

+
+
MaxEval
+
(integer) Default is 1000000. Places an upper limit on the number of function evaluations allowed.
+
AbsoluteError
+
(number) Default is 0. Sets the termination criterion for the absolute error in the integral.
+
RelativeError
+
(number) Default is 1e-6. Sets the termination criterion for the relative error in the integral.
+
Parallelize
+
(boolean) Default is false. If true, the integrand may be evaluated in parallel. In this case, the function must accept an integer as the first argument corresponding to the number of evaluations required, and subsequent parameters are tables containing the set of independent variables for each evaluation. The function should then return a table containg all the results in the same order.
+
+
+
+
+

Return values:

+
+
Returns the integrated value and an estimate of the error.
+
+ +
+
+S4.arg
+

When used with the -a switch, the value of S4.arg is set to the command line switch argument. +This is a convenient way of passing command line arguments to S4 scripts, or in parallel environments for specifying machine IDs.

+

When no command line switch is specified, S4.arg is nil.

+

Multiple variables may be passed in by passing in multiple Lua statements:

+
./S4 -a "a=1;b=2;c=3" input.lua
+
+

Then within the script, the variables may be set with the statement:

+
pcall(loadstring(S4.arg))
+
+
+
+ +
+
+S4.MPIRank
+

On a version of S4 with MPI support, gives the MPI machine rank (0-based index of processor node). For versions without MPI support, this is always 0.

+
+ +
+
+S4.MPISize
+

On a version of S4 with MPI support, gives the MPI size (total number of processor nodes). For versions without MPI support, this is always 1.

+
+ +
+
+

Simulation object

+
+
+class S4.Simulation
+

The Simulation object is the primary object which computes solutions to systems. +When a new Simulation object is requested from NewSimulation(), all settings are in a blank state, with no materals, layers, or excitation. +When solutions are requested, only a minimal set of internal computations are performed in order to satisfy the request.

+
+ +
+

Parameter specification

+
+
+Simulation:SetLattice(L)
+
+Simulation:SetLattice({x1, y1}, {x2, y2})
+

Sets the real-space lattice vectors.

+

Usage:

+
S:SetLattice(L)
+S:SetLattice({x1,y1}, {x2,y2})
+
+

Arguments:

+
+
This function can take a single numeric argument, which sets the period for a 1D lattice. +This function can also take two table arguments, each of which must have two numeric elements. +The first table specifies the x- and y-coordinates of the first lattice basis vector, while the second table specifies the second basis vector. The basis vectors should have positive orientation (the cross product of the first with the second should yield a vector with positive z-coordinate).
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetNumG(n)
+
+

Sets the maximum number of in-plane (x and y) Fourier expansion orders to use. +All fields and eigenmodes of the system use the same Fourier basis of the same dimension.

+

The computation time is roughly proportional to the cube of this number, and the memory usage is roughly proportional to the square.

+
+

Usage:

+
S:SetNumG(n)
+
+

Arguments:

+
+
+
n
+
(integer) The desired maximum number of Fourier orders to use. This number is an upper bound because internally, the Fourier lattice k-vectors (referred to as the G-vectors) are found in a symmetry-preserving manner starting from the origin and retaining those of shortest length. To obtain the actual number of Fourier orders used, use GetNumG().
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:AddMaterial(name, {eps_r, eps_i})
+
+Simulation:AddMaterial(name, eps_tensor)
+
+
Adds a new material with a specified dielectric constant.
+

Usage:

+
S:AddMaterial(name, {eps_r, eps_i})
+S:AddMaterial(name, {
+    {xx_r, xx_i}, {xy_r, xy_i}, {xz_r, xz_i},
+    {yx_r, yx_i}, {yy_r, yy_i}, {yz_r, yz_i},
+    {zx_r, zx_i}, {zy_r, zy_i}, {zz_r, zz_i}
+    })
+
+

Arguments:

+
+
+
name
+
(string) The name of the material. Each material must have a unique name.
+
eps_r, eps_r
+
(number) The real and imaginary parts of the relative permittivity of the material. The imaginary part should be positive.
+
xx_r, xx_i, xy_r, ...
+
(number) Components of the relative permittivity tensor of the material. Currently the xz, yz, zx, and zy components are ignored and assumed to be zero.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetMaterial(name, {eps_r, eps_i})
+
+Simulation:SetMaterial(name, eps_tensor)
+
+
Updates an existing material with a new dielectric constant or adds a material if none exists.
+

Usage:

+
S:SetMaterial(name, {eps_r, eps_i})
+S:SetMaterial(name, {
+    {xx_r, xx_i}, {xy_r, xy_i}, {xz_r, xz_i},
+    {yx_r, yx_i}, {yy_r, yy_i}, {yz_r, yz_i},
+    {zx_r, zx_i}, {zy_r, zy_i}, {zz_r, zz_i}
+    })
+
+

Arguments:

+
+
+
name
+
(string) The name of the material to update, or the name of a new material if no material by that name exists.
+
eps_r, eps_r
+
(number) The real and imaginary parts of the relative permittivity of the material. The imaginary part should be positive.
+
xx_r, xx_i, xy_r, ...
+
(number) Components of the relative permittivity tensor of the material. Currently the xz, yz, zx, and zy components are ignored and assumed to be zero.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:AddLayer(name, thickness, material)
+
+
Adds a new unpatterned layer with a specified thickness and material.
+

Usage:

+
S:AddLayer(name, thickness, material)
+
+

Arguments:

+
+
+
name
+
(string) The name of the layer. Each layer must have a unique name.
+
thickness
+
(number) The thickness of the layer.
+
material
+
(string) The name of the material which comprises the layer. With patterning, this is the default (background) material of the layer.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetLayer(name, thickness, material)
+
+
Updates an existing layer with a new thickness and removes all layer patterning. +If no matching layer is found, adds a new unpatterned layer with a specified thickness and material. +The behavior is undefined if the new material does not match the old material during an update (currently, the new material is ignored, but this may change in the future). +If only the thickness needs to be modified, use SetLayerThickness().
+

Usage:

+
S:SetLayer(name, thickness, material)
+
+

Arguments:

+
+
+
name
+
(string) The name of the layer to update. If no layer by that name exists, a new layer is created with this name.
+
thickness
+
(number) The new thickness of the layer.
+
material
+
(string) The name of the material which comprises the layer.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetLayerThickness(name, thickness)
+
+
Updates an existing layer with a new thickness. +Previously cached layer eigenmodes are preserved, making this function the preferred way to update a layer’s thickness.
+

Usage:

+
S:SetLayerThickness(name, thickness)
+
+

Arguments:

+
+
+
name
+
(string) The name of the layer to update.
+
thickness
+
(number) The new thickness of the layer.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:AddLayerCopy(name, thickness, original_name)
+
+
Adds a new layer with a specified thickness, but identical patterning as another existing layer. +Note that this merely creates a reference to the copied layer; further patterning of the copied layer also affects the new layer. Additionally, a copy of a copy cannot be made.
+

Usage:

+
S:AddLayerCopy(name, thickness, original_name)
+
+

Arguments:

+
+
+
name
+
(string) The name of the new layer, different from the layer being copied.
+
thickness
+
(number) The thickness of the new layer.
+
original_name
+
(string) The name of the layer which whose pattern is to be copied. That layer cannot itself be a copy of a layer.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetLayerPatternCircle(layer, material, center, radius)
+
+
Adds a (filled) circle of a specified material to an existing non-copy layer. +The circle should not intersect any other patterning shapes, but may contain or be contained within other shapes.
+

Usage:

+
S:SetLayerPatternCircle(layer, material, center, radius)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer to pattern. This layer cannot be a copy of another layer.
+
material
+
(string) The name of the material which fills the interior of the circle.
+
center
+
(numeric table, length 2) x- and y-coordinates of the center of the circle relative to the center of the unit cell (the origin).
+
radius
+
(number) Radius of the circle.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetLayerPatternEllipse(layer, material, center, angle, halfwidths)
+
+
Adds a (filled) ellipse of a specified material to an existing non-copy layer. +The ellipse should not intersect any other patterning shapes, but may contain or be contained within other shapes.
+

Usage:

+
S:SetLayerPatternEllipse(layer, material, center, angle, halfwidths)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer to pattern. This layer cannot be a copy of another layer.
+
material
+
(string) The name of the material which fills the interior of the ellipse.
+
center
+
(numeric table, length 2) x- and y-coordinates of the center of the ellipse relative to the center of the unit cell (the origin).
+
angle
+
(number) The angle (in degrees) by which the x-axis of the ellipse should be rotated (CCW).
+
halfwidths
+
(numeric table, length 2) The lengths of the semi-major axes of the ellipse. For an angle of 0, the first length is the semi-major axis in the x-direction, and the second length is the semi-major axis in the y-direction.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetLayerPatternRectangle(layer, material, center, angle, halfwidths)
+
+
Adds a (filled) rectangle of a specified material to an existing non-copy layer. +The rectangle should not intersect any other patterning shapes, but may contain or be contained within other shapes.
+

Usage:

+
S:SetLayerPatternRectangle(layer, material, center, angle, halfwidths)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer to pattern. This layer cannot be a copy of another layer.
+
material
+
(string) The name of the material which fills the interior of the rectangle.
+
center
+
(numeric table, length 2) x- and y-coordinates of the center of the rectangle relative to the center of the unit cell (the origin).
+
angle
+
(number) The angle (in degrees) by which the x-axis of the rectangle should be rotated (CCW).
+
halfwidths
+
(numeric table, length 2) The half-widths of the rectangle. For an angle of 0, the first length is half the width of the rectangle in the x-direction, and the second length is half the height in the y-direction.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetLayerPatternPolygon(layer, material, center, angle, vertices)
+
+
Adds a (filled) polygon of a specified material to an existing non-copy layer. +The polygon should not self-intersect nor intersect any other patterning shapes, but may contain or be contained within other shapes. The polygon must also be specified with positive orientation (the vertices circle CCW about an interior point).
+

Usage:

+
S:SetLayerPatternPolygon(layer, material, center, angle, vertices)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer to pattern. This layer cannot be a copy of another layer.
+
material
+
(string) The name of the material which fills the interior of the polygon.
+
center
+
(numeric table, length 2) x- and y-coordinates of the center of the polygon relative to the center of the unit cell (the origin).
+
angle
+
(number) The angle (in degrees) by which the polygon should be rotated (CCW).
+
vertices
+
(numeric table, length 2*vertex_count) The x- and y-coordinates of the vertices of the (unrotated) polygon, one after another. +Thus, vertices[1] is the x-coordinate of the first vertex and vertices[2] is its y-coordinate, and vertices[3] is the x-coordinate of the second vertex, etc.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetExcitationPlanewave({phi, theta}, {s_amp, s_phase}, {p_amp, p_phase}, order)
+
+
Sets the excitation to be a planewave incident upon the front (first layer specified) of the structure. +If both tilt angles are specified to be zero, then the planewave is normally incident with the electric field polarized along the x-axis for the p-polarization. +The phase of each polarization is defined at the origin (z = 0).
+

Usage:

+
S:SetExcitationPlanewave({phi,theta}, {s_amp, s_phase}, {p_amp, p_phase}, order)
+
+

Arguments:

+
+
+
phi, theta
+
(number) Angles in degrees. phi and theta give the spherical coordinate angles of the planewave k-vector. +For zero angles, the k-vector is assumed to be (0, 0, kz), while the electric field is assumed to be (E0, 0, 0), and the magnetic field is in (0, H0, 0). +The angle phi specifies first the angle by which the E,H,k frame should be rotated (CW) about the y-axis, and the angle theta specifies next the angle by which the E,H,k frame should be rotated (CCW) about the z-axis. Note the different directions of rotations for each angle.
+
s_amp, p_amp
+
(number) The electric field amplitude of the s- and p-polarizations of the planewave.
+
s_phase, p_phase
+
(number) The phase of the s- and p-polarizations of the planewave, relative to z = 0 (the beginning of the first layer).
+
order
+
(number) An optional positive integer specifying which order (mode index) to excite. Defaults to 1. This is the same index that GetDiffractionOrder returns.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetExcitationExterior(table)
+
+
Low level function to set excitations by a superposition of incident modes of the exterior layers. For unpatterned layers, the incident modes are forward propagating planewaves in the front, and backward propagating planewaves in the back.
+

Usage:

+
S:SetExcitationExterior{
+    { G-index, pol, { amp-re, amp-im } },
+    ...
+}
+
+

Arguments:

+
+
+
G-index
+
(number) Index of the mode. This is the same index that GetDiffractionOrder returns.
+
pol
+
(string) Either ‘x’ or ‘y’ for the polarization of the electric field in unpatterned layers.
+
amp-re, amp-im
+
(number) Real and imaginary parts of the amplitude coefficient for the mode.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation:SetFrequency(freqr, freqi = 0)
+
+
Sets the operating frequency of the system (and excitation).
+

Usage:

+
S:SetFrequency(freqr, freqi)
+
+

Arguments:

+
+
+
freqr
+
(number) The (real) frequency of the excitation. This is not the angular frequency (the angular frequency is 2pi times of this).
+
freqi
+
(number) The imaginary frequency of the system. This parameter is typically not specified and assumed to be zero. When specified (typically for mode solving), this parameter should be negative for a physical (decaying in time) system.
+
+
+

Return values:

+
+
None
+
+ +
+
+

Outputs requiring no solutions

+
+
+Simulation:GetReciprocalLattice()
+
+
Retrieves the reciprocal lattice basis vectors. +The vectors lack the scaling by 2pi (multiply them by 2pi to obtain the true reciprocal lattice basis vectors).
+

Usage:

+
Gu,Gv = S:GetReciprocalLattice()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
+
Gu, Gv
+
The first and second reciprocal lattice basis vectors. +Their relative geometric orientation is the same as the lattice specified with SetLattice(). +Each vector is a table of length 2, holding the x- and y-coordinates of the vector.
+
+
+
+ +
+
+Simulation:GetEpsilon({x, y, z})
+
+

Retrieves the dielectric constant at a particular point in the system by reconstructing the Fourier series using the G-vectors of the system.

+

Note that this reconstruction is not representative of the actual dielectric constant profile used in simulations (such a notion is not meaningful). The reconstruction is created using the closed-form Fourier series coefficients of the specified patterning, summed over the terms comprising the G-vector list obtained from lattice truncation. This function exists to provide an intuitive sense for the spatial resolution of a particular G-vector truncation order.

+
+

Usage:

+
eps_r, eps_i = S:GetEpsilon({x, y, z})
+
+

Arguments:

+
+
+
x, y, z
+
(number) The coordinates of the point at which to retrieve the dielectric constant.
+
+
+

Return values:

+
+
+
eps_r, eps_i
+
The real and imaginary parts of the dielectric constant.
+
+
+
+ +
+
+Simulation:OutputLayerPatternDescription(name, filename)
+
+
Outputs a list of PostScript commands to render the exact layer pattern description from the specified patterning commands. Assumes letter-sized paper.
+

Usage:

+
S:OutputLayerPatternDescription(name, filename)
+
+

Arguments:

+
+
+
name
+
(string) Name of the layer whose pattern description should be output.
+
filename
+
(string, optional) Filename to which the description should be output. If this argument is not provided, standard output is used.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:OutputLayerPatternRealization(name, Nu, Nv, filename)
+
+

Outputs a Gnuplot format dump of the Fourier series reconstruction of the dielectric constant in the unit cell. Note that the output will appear distorted for non-orthogonal unit cells.

+

Note that this reconstruction is not representative of the actual dielectric constant profile used in simulations (such a notion is not meaningful). The reconstruction is created using the closed-form Fourier series coefficients of the specified patterning, summed over the terms comprising the G-vector list obtained from lattice truncation. This function exists to provide an intuitive sense for the spatial resolution of a particular G-vector truncation order.

+
+

Usage:

+
+
S:OutputLayerPatternRealization(name, Nu, Nv, filename)
+

Arguments:

+
+
+
name
+
The name of the layer whose pattern should be output.
+
Nu, Nv
+
The number of discretization cells in the first and second lattice basis direction to use. The total number of output points is Nu*Nv.
+
filename
+
(string, optional) Filename to which the pattern should be output. If this argument is not provided, standard output is used.
+
+
+

Return values:

+
+
None.
+
+ +
+
+

Outputs requiring solutions

+
+
+Simulation:OutputStructurePOVRay([filename])
+
+
Outputs a POV-Ray script that will render one unit cell of the structure in 3D. Materials named air or vacuum (case insensitive) will be completely transparent.
+

Usage:

+
S:OutputStructurePOVRay(filename)
+
+

Arguments:

+
+
+
filename
+
(string, optional) Filename to which the structure should be output. If this argument is not provided, standard output is used.
+
+
+

Return values

+
+
None.
+
+ +
+
+Simulation:GetNumG()
+
+
Returns the specified number of Fourier series orders to use (number of G-vectors), or, if a solution has been computed, the actual number of G-vectors used.
+

Usage:

+
n = S:GetNumG()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
+
n
+
If no solutions have been computed, the upper bound of G-vectors specified. If a solution has been computed, then n is the actual number of G-vectors used.
+
+
+
+ +
+
+Simulation:GetGList()
+
+
Returns a table of reciprocal lattice coordinates of the Fourier series orders used. +The coordinates are in the reciprocal lattice basis, and so they are integers.
+

Usage:

+
G = S:GetGList()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
+
G
+
A table of tables of length 2 holding the pairs of integer recprical lattice coordinates.
+
+
+
+ +
+
+Simulation:GetDiffractionOrder(m, n)
+
+
Returns the index (1-based) of a particular diffraction order. +The index can be used directly in GetPowerFluxByOrder to obtain the diffracted power of a particular order. +The coordinate arguments are in the reciprocal lattice basis, and so they are integers. +A particular diffraction order is only a meaningful concept in a uniform (unpatterned) layer, otherwise the diffraction order corresponds to an arbitrary layer eigenfunction index.
+

Usage:

+
i = S:GetDiffractionOrder(m, n)
+
+

Arguments:

+
+
+
m, n
+
(integer) The diffracted order. These numbers are in the reciprocal lattice basis.
+
+
+

Return values:

+
+
+
i
+
The index of the diffraction order.
+
+
+
+ +
+
+Simulation:GetAmplitudes(layer, offset)
+
+
Returns the raw mode amplitudes within a particular layer. +For uniform (unpatterned) layers, the modes are simply the diffracted orders, and the indexing of the returned amplitudes corresponds to the value obtained from GetDiffractedOrder. +The first value is guaranteed to be the straight transmitted or specularly reflected diffraction order. +For patterned layers, there is typically no meaningful information in these amplitudes.
+

Usage:

+
forw,back = S:GetAmplitudes(layer, offset)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which to obtain mode amplitudes.
+
offset
+
(number) The z-offset at which to obtain the mode amplitudes.
+
+
+

Return values:

+
+
+
forw,back
+
Tables of length 2*NumG containing the complex amplitudes of each forward and backward mode. Each complex amplitude is a table of length 2 containing real and imaginary parts.
+
+
+
+ +
+
+Simulation:GetPowerFlux(layer, offset=0)
+
+
Returns the integral of the power (Poynting) flux density over a unit cell surface normal to the z-direction. +In other words, the z-component of the power flux is returned.
+

Usage:

+
forw_r, back_r, forw_i, back_i = S:GetPowerFlux(layer, offset)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which the integration surface lies.
+
offset
+
(number, optional) The z-offset of the integration surface from the beginning of the layer. This only matters for lossy layers.
+
+
+

Return values:

+
+
+
forw_r, forw_i
+
The real and imaginary parts of the forward component of the complex Poynting vector. Note that the result is not time averaged (no factor of 0.5 multiplied in). The forward component is defined as (E_total^* x H_forw + H_total^* x E_forw) / 2, where E_forw and H_forw are the fields reconstructed from only the forward propagating waveguide modes of the layer.
+
back_r, back_i
+
The real and imaginary parts of the backward component of the complex Poynting vector. Note that the result is not time averaged (no factor of 0.5 multiplied in). An analogous definition of the backward component of the Poynting vector follows from above.
+
+
+
+ +
+
+Simulation:GetPowerFluxByOrder(layer, offset)
+
+
Returns the integral of the power (Poynting) flux density over a unit cell surface normal to the z-direction for each Fourier series order. +In other words, the z-component of the Poynting flux for each order is returned.
+

Usage:

+
P = S:GetPowerFluxByOrder(layer, offset)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which the integration surface lies.
+
offset
+
(number) The z-offset of the integration surface from the beginning of the layer. This only matters for lossy layers.
+
+
+

Return values:

+
+
+
P
+
A table with length equal to the number of Fourier series orders used. +Each entry of the table is a table of length 4, whose values are: forw_r, back_r, forw_i, back_i. +These four quantities are described in the section for GetPowerFlux().
+
+
+
+ +
+
+Simulation:GetStressTensorIntegral(layer, offset)
+
+
Returns the integral of the electromagnetic stress tensor over a unit cell surface normal to the z-direction.
+

Usage:

+
Txr, Tyr, Tzr, Txi, Tyi, Tzi = S:GetStressTensorIntegral(layer, offset)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which the integration surface lies.
+
offset
+
(number) The z-offset of the integration surface from the beginning of the layer.
+
+
+

Return values:

+
+
+
Txr, Txi
+
The real and imaginary parts of the x-component of the stress tensor integrated over the specified surface, assuming a unit normal vector in the +z direction. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
Tyr, Tyi, Tzr, Tzi
+
Analogous to above.
+
+
+
+ +
+
+Simulation:GetLayerEnergyDensityIntegral(layer)
+
+
Returns the volume integral of the electromagnetic energy density (epsilon*|E|^2 + |H|^2) over a unit cell throughout the entire thickness of a layer.
+

Usage:

+
Ur,Ui = S:GetLayerEnergyDensityIntegral(layer)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which to integrate over.
+
+
+

Return values:

+
+
+
Ur,Ui
+
The real and imaginary parts of the integral of the energy density throughout the volume of the layer’s unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation:GetLayerElectricEnergyDensityIntegral(layer)
+
+
Returns the volume integral of the electric energy density (epsilon*|E|^2) over a unit cell throughout the entire thickness of a layer.
+

Usage:

+
Ur,Ui = S:GetLayerElectricEnergyDensityIntegral(layer)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which to integrate over.
+
+
+

Return values:

+
+
+
U
+
The real and imaginary parts of the integral of the electric energy density throughout the volume of the layer’s unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation:GetLayerMagneticEnergyDensityIntegral(layer)
+
+
Returns the volume integral of the magnetic energy density (|H|^2) over a unit cell throughout the entire thickness of a layer.
+

Usage:

+
Ur,Ui = S:GetLayerMagneticEnergyDensityIntegral(layer)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which to integrate over.
+
+
+

Return values:

+
+
+
Ur,Ui
+
The real and imaginary parts of the integral of the magnetic energy density throughout the volume of the layer’s unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation:GetLayerElectricFieldIntensityIntegral(layer)
+
+
Returns the volume integral of the squared electric field intensity (|E|^2) over a unit cell throughout the entire thickness of a layer.
+

Usage:

+
Ur,Ui = S:GetLayerElectricFieldIntensityIntegral(layer)
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which to integrate over.
+
+
+

Return values:

+
+
+
Ur,Ui
+
The real and imaginary parts of the integral of the square electric field intensity throughout the volume of the layer’s unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation:GetLayerZIntegral(layer, {x, y})
+
+
Returns the line integral along z (depth direction) of the squared magnitudes of electric and magnetic field components (|Ex|^2, |Ey|^2, etc.) throughout the entire thickness of a layer.
+

Usage:

+
IEx, IEy, IEz, IHx, IHy, IHz = S:GetLayerZIntegral(layer, {x, y})
+
+

Arguments:

+
+
+
layer
+
(string) The name of the layer in which to integrate through.
+
x,y
+
(number) The in-plane coordinates at which to integrate.
+
+
+

Return values:

+
+
+
IEx,IEy,IEz,IHx,IHy,IHz
+
The integral of the squared magnitudes of electric and magnetic field components throughout the thickness of the layer. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation:GetEField({x, y, z})
+
+
Returns the electric field at a particular point within the structure.
+

Usage:

+
Exr, Eyr, Ezr, Exi, Eyi, Ezi = S:GetEField({x, y, z})
+
+

Arguments:

+
+
+
x, y, z
+
(number) The coordinates of the point at which to obtain the field.
+
+
+

Return values:

+
+
+
Exr, Exi
+
The real and imaginary parts of the complex electric field at the specified point. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
Eyr, Eyi, Ezr, Ezi
+
Analogous to above.
+
+
+
+ +
+
+Simulation:GetHField({x, y, z})
+
+
Returns the magnetic field at a particular point within the structure.
+

Usage:

+
Hxr, Hyr, Hzr, Hxi, Hyi, Hzi = S:GetHField({x, y, z})
+
+

Arguments:

+
+
+
x, y, z
+
(number) The coordinates of the point at which to obtain the field.
+
+
+

Return values:

+
+
+
Hxr, Hxi
+
The real and imaginary parts of the complex magnetic field at the specified point. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
Hyr, Hyi, Hzr, Hzi
+
Analogous to above.
+
+
+
+ +
+
+Simulation:GetFields({x, y, z})
+
+
Returns the electric and magnetic field at a particular point within the structure. +Note that it is more efficient to call this function when both fields are needed.
+

Usage:

+
Exr, Eyr, Ezr, Hxr, Hyr, Hzr, Exi, Eyi, Ezi, Hxi, Hyi, Hzi = S:GetFields({x, y, z})
+
+

Arguments:

+
+
+
x, y, z
+
(number) The coordinates of the point at which to obtain the field.
+
+
+

Return values:

+
+
+
Exr, Exi
+
The real and imaginary parts of the complex electric field at the specified point. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
Eyr, Eyi, Ezr, Ezi, Hxr, Hxi, Hyr, Hyi, Hzr, Hzi
+
Analogous to above.
+
+
+
+ +
+
+Simulation:GetFieldPlane(z, {nu, nv}, format, basefilename)
+
+
Returns the electric and magnetic fields on a regular grid over the unit cell (fundamental parallelogram) at a particular z coordinate. +It is more efficient to use this function than GetFields().
+

Usage:

+
E,H = S:GetFieldPlane(z, {nu, nv}, 'Array')
+S:GetFieldPlane(z, {nu, nv}, 'FileWrite', basename)
+S:GetFieldPlane(z, {nu, nv}, 'FileAppend', basename)
+
+

Arguments:

+
+
+
z
+
(number) The z-coordinate of the plane on which to obtain the field.
+
nu,nv
+
(integer) The number of sample points to use in each lattice vector direction.
+
format
+

(string) Specifies the format of the output. Current choices are:

+
+
Array
+
Returns a pair of arrays of dimension nu by nv, each element is a table of length 3, containing tables of length 2 with the real and imaginary parts of the E or H field components.
+
FileWrite
+
Outputs the field data to files, overwriting the files.
+
FileAppend
+
Outputs the field data to files, appending to the files. This is useful of volume fields are needed.
+
+
+
basefilename
+
(string) The base filename for file output. The outputs are named basefilename .. '.E' and basefilename .. '.H'.
+
+
+

Return values:

+
+
+
E,H
+
Only returned if format is ‘Array’. +Arrays of dimension nu by nv, each element is a table of length 3, containing tables of length 2 with the real and imaginary parts of the E or H field.
+
+
+
+ +
+
+Simulation:GetSMatrixDeterminant()
+
+
Returns the determinant of the S-matrix (scattering matrix) of the entire structure. +The determinant is an analytic function in the complex frequency plane and has poles at the complex modal frequencies of the system.
+

Usage:

+
mantr, manti, base, expo = S:GetSMatrixDeterminant()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
+
mantr, manti
+
The determinant typically causes overflow or underflow, so it is returned as a mantissa multiplying a base raised to an exponent. These values are the real and imaginary parts of the mantissa. The value of the determinant is (mantr+i*manti)*base^expo.
+
base
+
The base of the determinant representation (see above).
+
expo
+
The exponent of the determinant representation (see above).
+
+
+
+ +
+
+

Options

+
+
+Simulation:UseLanczosSmoothing(use)
+
+
Enables or disables smoothing of the Fourier series representations of the layer dielectric constants using the Lanczos sigma factor (box filtering). This reduces the Gibbs phenomenon ringing in the real space reconstruction.
+

Usage:

+
S:UseLanczosSmoothing(use)
+
+

Arguments:

+
+
+
use
+
(boolean, optional) Indicates whether to enable smoothing. If this argument is not provided, smoothing is enabled.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:UseDiscretizedEpsilon(use)
+
+

Enables or disables the use of discretization in generating the Fourier coefficients of the in-plane epsilon profiles, instead of using values from closed-form equations. When enabled, the coefficients are obtained by FFT.

+

See the Fourier Modal Method formulations for details.

+
+

Usage:

+
S:UseDiscretizedEpsilon(use)
+
+

Arguments:

+
+
+
use
+
(boolean, optional) Indicates whether to use a discretized epsilon. If this argument is not provided, use of a discretized epsilon is enabled.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:UsePolarizationDecomposition(use)
+
+

Enables or disables the use of proper in-plane Fourier factorization rules by decomposing fields into a polarization basis which conforms to the material boundaries. +The polarization basis field is generated automatically by computing a quasi-harmonic vector field everywhere tangent to the layer pattern boundaries. +This option is not guaranteed to work in the presence of tensor dielectric constants.

+

Enabling this feature typically improves convergence with respect to the number of G-vectors. +See the Fourier Modal Method formulations for details.

+
+

Usage:

+
S:UsePolarizationDecomposition(use)
+
+

Arguments:

+
+
+
use
+
(boolean, optional) Indicates whether to enable polarization decomposition. If this argument is not provided, polarization decomposition is enabled.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:UseSubpixelSmoothing(use)
+
+

Enables or disables the use of second-order accurate epsilon averaging rules within a pixel. +The average epsilon within a pixel is computed using the fill factor of each material and the interface direction.

+

Enabling this feature may improve convergence with respect to the number of G-vectors. +See the Fourier Modal Method formulations for details.

+
+

Usage:

+
S:UseSubpixelSmoothing(use)
+
+

Arguments:

+
+
+
use
+
(boolean, optional) Indicates whether to enable subpixel smoothing. If this argument is not provided, subpixel smoothing is enabled.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:UseJonesVectorBasis(use)
+
+

This option only has an effect with UsePolarizationDecomposition(). +When enabled, a Jones vector basis field is used instead of a conformal harmonic field.

+

Enabling this feature may improve convergence with respect to the number of G-vectors. +See the Fourier Modal Method formulations for details.

+
+

Usage:

+
S:UseJonesVectorBasis(use)
+
+

Arguments:

+
+
+
use
+
(boolean, optional) Indicates whether to use a Jones vector basis. If this argument is not provided, use of a Jones vector basis is enabled.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:UseNormalVectorBasis(use)
+
+

This option only has an effect with UsePolarizationDecomposition(). +When enabled, the resulting vector field is normalized. Where the vector field is zero, the unit vector in the x-direction is used.

+

Enabling this feature may improve convergence with respect to the number of G-vectors. +See the Fourier Modal Method formulations for details.

+
+

Usage:

+
S:UseNormalVectorBasis(use)
+
+

Arguments:

+
+
+
use
+
(boolean, optional) Indicates whether to use a normalized vector basis. If this argument is not provided, use of a normalized vector basis is enabled.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:SetResolution(use)
+
+

This option only has an effect with UseDiscretizedEpsilon() or UseSubpixelSmoothing(). +This function sets the resolution of the FFT grid and vector field generated by EnablePolarizationDecomposition(). +The resolution is multiplied by the largest G-vector extent (integer lattice coordinate), and should be at least 2 to satisfy the Nyquist limit. It is best to use a number with small integer factors in order for the FFT to be computed efficiently. The size of each dimension of the FFT is obviously proportional to this value. The default is 8.

+

See the Fourier Modal Method formulations for details.

+
+

Usage:

+
S:SetResolution(n)
+
+

Arguments:

+
+
+
n
+
The oversampling factor. Must be at least 2.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:SetBasisFieldDumpPrefix(prefix)
+
+
Setting this option to a filename prefix causes the vector field used by the polarization decomposition to be dumped to files (one for each layer) in Gnuplot format. +The files are named by concatenating the provided prefix string with each layer’s name.
+

Usage:

+
S:SetBasisFieldDumpPrefix(prefix)
+
+

Arguments:

+
+
+
prefix
+
(string, optional) When provided, the filename prefix is set to the given string. This can be an empty string. If this argument is not provided, the basis field dump is disabled.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:SetLatticeTruncation(trunc)
+
+
Sets the type of lattice truncation to use when selecting G-vectors.
+

Usage:

+
S:SetLatticeTruncation(trunc)
+
+

Arguments:

+
+
+
trunc
+

(string) Can be one of the following values:

+
+
Circular
+
This is the default. The G-vectors are selected to have shortest length (by l2 norm).
+
Parallelogramic
+
Chooses the G-vectors within a parallelogram aligned with the reciprocal lattice basis. The number chosen will always be a perfect square of an odd number.
+
+
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:SetVerbosity(level)
+
+
Sets the level of diagnostic output generated by the program.
+

Usage:

+
S:SetVerbosity(level)
+
+

Arguments:

+
+
+
level
+
(integer, optional) The larger this value, the more status output is generated. Valid values are in the range of 0-9, inclusive. A value of 0 disables all status output.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation:UseLessMemory(use)
+
+
Setting this option will prevent storage of certain intermediate results. This will save approximately 30% memory for non-trivial layers. +The drawback is slower computation of any output quantities that require solutions.
+

Usage:

+
+
S:UseLessMemory(use)
+

Arguments:

+
+
+
use
+
(boolean, optional) Indicates whether to use less memory. If this argument is not provided, lower memory usage is enabled.
+
+
+

Return values:

+
+
None.
+
+ +
+
+

Miscellaneous

+
+
+Simulation:Clone()
+
+
Duplicates an existing Simulation object, copying all materials, layers, and excitation information. +No partial solution information is copied.
+

Usage:

+
S2 = S:Clone()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
A copy of the Simulation object.
+
+ +
+
+
+

SpectrumSampler object

+
+
+class S4.SpectrumSampler
+

The SpectrumSampler object provides a convenient way to sample spectral information of a system. +For example, it is used to resolve sharp peaks in transmission spectra. +Interaction with a SpectrumSampler object is by contract; a new frequency is retrieved from it by which simulation results at that frequency are computed, and then the results are submitted.

+

The frequencies given out by a SpectrumSampler object aim to produce a visually pleasing plot of the resulting spectrum by limiting the maximum normalized bend angles between adjacent line segments of the plot.

+

A typical usage is shown below:

+
function f(x) -- example function
+    return math.sin(x)
+end
+sampler = S4.NewSpectrumSampler(0.1, 0.9, -- start and end frequencies
+    { -- table of options
+    InitialNumPoints = 33,
+    RangeThreshold = 0.001,
+    MaxBend = math.cos(math.rad(10)),
+    MinimumSpacing = 1e-6
+    })
+while not sampler:IsDone() do
+    x = sampler:GetFrequency()
+    y = f(x) -- compute the desired result
+    sampler:SubmitResult(y)
+end
+
+spectrum = sampler:GetSpectrum()
+for i,xy in ipairs(spectrum) do
+    print(xy[1],xy[2])
+end
+
+
+ +
+
+SpectrumSampler:IsDone()
+
+
Queries whether the SpectrumSampler has completed sampling. +When sampling has been completed, no further frequencies should be requested from the SpectrumSampler object, and no further results should be submitted.
+

Usage:

+
done = sampler:IsDone()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
A boolean value indicating whether sampling has completed.
+
+ +
+
+SpectrumSampler:GetFrequency()
+
+
Retrieves the next frequency at which to sample the spectrum. This function should only be used if the SpectrumSampler object was created with Parallize set to false (the default).
+

Usage:

+
freq = sampler:GetFrequency()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
The (numeric) frequency at which the next result should be computed and submitted.
+
+ +
+
+SpectrumSampler:GetFrequencies()
+
+
Retrieves the next set of frequencies at which to sample the spectrum. This function should only be used if the SpectrumSampler object was created with Parallize set to true.
+

Usage:

+
freqlist = sampler:GetFrequency()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
A list of (numeric) frequencies at which the next results should be computed and submitted.
+
+ +
+
+SpectrumSampler:SubmitResult(result)
+
+
Submits a result to the SpectrumSampler object. The result is assumed to be at the frequency of the last requested frequency. This function should only be used if the SpectrumSampler object was created with Parallize set to false (the default).
+

Usage:

+
done = sampler:SubmitResult(result)
+
+

Arguments:

+
+
+
result
+
(number) The result to submit. The result may be any value (for example, the transmission through a structure).
+
+
+

Return values:

+
+
A boolean value indicating whether sampling has completed.
+
+ +
+
+SpectrumSampler:SubmitResults(result_list)
+
+
Submits a set of results to the SpectrumSampler object. The results are assumed to be at the frequencies of the last requested frequencies. This function should only be used if the SpectrumSampler object was created with Parallize set to true.
+

Usage:

+
done = sampler:SubmitResults(result_list)
+
+

Arguments:

+
+
+
result_list
+
(table) The list of results to submit. The length of this table must match the number of frequencies obtained from the previous call to GetFrequencies.
+
+
+

Return values:

+
+
A boolean value indicating whether sampling has completed.
+
+ +
+
+SpectrumSampler:GetSpectrum()
+
+
Retrieves a list of all sampled frequencies and submitted results. +This function should only be used when the SpectrumSampler object indicates that sampling is complete.
+

Usage:

+
valarray = sampler:GetSpectrum()
+
+

Arguments:

+
+
None.
+

Return values:

+
+
An array (with length equal to the number of samples) of pairs (arrays of length 2) containing the sampled frequency and corresponding submitted result.
+
+ +
+
+

Interpolator object

+
+
+class S4.Interpolator
+

The Interpolator object provides a tool to perform various types of interpolation on data. +The most common use is to interpolate between experimentally determined values for dieletric constants. +A typical usage is shown below:

+
interpolator = S4.NewInterpolator('linear', {
+    {3.0, {14.2, 32}}, -- x, and list of y values
+    {5.4, {4.6, 10}},
+    {5.7, {42.7, 20}},
+    {8.0, {35.2, 40}}
+    })
+
+for x = 0, 10, 0.1 do
+    y1, y2 = interpolator:Get(x)
+    print(x, y1, y2)
+end
+
+

At each x (abscissa) value, any number of y (ordinate) values can be specified for interpolation.

+
+ +
+
+Interpolator:Get(x)
+
+
Retrieves the interpolated ordinates for a given abscissa value.
+

Usage:

+
y1, y2, ... = interpolator:Get(x)
+
+

Arguments:

+
+
+
x
+
(number) The abscissa value at which to interpolate.
+
+
+

Return values:

+
+
A list of interpolated ordinate values.
+
+ +
+
+ + +
+
+
+ +
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/objects.inv b/doc/build/html/objects.inv new file mode 100644 index 0000000..0854b15 Binary files /dev/null and b/doc/build/html/objects.inv differ diff --git a/doc/build/html/py-modindex.html b/doc/build/html/py-modindex.html new file mode 100644 index 0000000..9409bba --- /dev/null +++ b/doc/build/html/py-modindex.html @@ -0,0 +1,135 @@ + + + + + + + + Python Module Index — S4 1.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +

Python Module Index

+ +
+ s +
+ + + + + + + +
 
+ s
+ S4 +
+ + +
+
+
+
+
+ +

Table Of Contents

+ + + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/python_api.html b/doc/build/html/python_api.html new file mode 100644 index 0000000..702258d --- /dev/null +++ b/doc/build/html/python_api.html @@ -0,0 +1,1036 @@ + + + + + + + + Python API reference — S4 1.1 documentation + + + + + + + + + + + + + + + +
+
+
+
+ +
+

Python API reference

+

S4 can be built as a Python extension, in addition to the original Lua interface. +The current Python interface is not as fully featured as the Lua interface, but it should ultimately achieve feature parity. +Much auxilliary functionality, such as numerical integration, is not included here since Numpy and Scipy can easily be used instead.

+
+

S4 module

+

All top level functions of S4 are located in the S4 library.

+
+
+S4.New(Lattice, NumBasis)
+

Returns a new Simulation object.

+

Usage:

+
S = S4.NewSimulation(Lattice=((1,0),(0,1)), NumBasis=100)
+
+
+

Arguments:

+
+
+
Lattice
+
Sets the lattice vectors for the structure. This can be a single real number in the case of a 1D periodic lattice, or a pair of vectors for a 2D periodic lattice.
+
NumBasis
+
Sets the maximum number of in-plane (x and y) Fourier expansion orders to use. +All fields and eigenmodes of the system use the same Fourier basis of the same dimension. +The computation time is roughly proportional to the cube of this number, and the memory usage is roughly proportional to the square. +This is equivalent to the “NumG” setting in the Lua interface.
+
+
+

Return values:

+
+
+
S
+
A new Simulation object.
+
+
+
+ +
+
+

Simulation object

+
+
+class S4.Simulation
+
+ +

The Simulation object is the primary object which computes solutions to systems. +When a new Simulation object is requested from New(), all settings are in a blank state, with no materals, layers, or excitation. +When solutions are requested, only a minimal set of internal computations are performed in order to satisfy the request.

+
+

Parameter specification

+
+
+Simulation.SetMaterial(Name, Epsilon)
+
+
Updates an existing material with a new dielectric constant or adds a material if none exists.
+

Usage:

+
S.SetMaterial(Name = 'Silicon, Epsilon = 12+0.01j)
+S.SetMaterial(Name = 'Silicon', Epsilon = (
+        (12+0.01j, 0, 0),
+        (0, 12+0.01j, 0),
+        (0, 0, 12+0.01j)
+        ))
+
+

Arguments:

+
+
+
Name
+
(string) The name of the material to update, or the name of a new material if no material by that name exists.
+
Epsilon
+
(number, complex number, or 3x3 tensor) The relative permittivity of the material. The imaginary part should generally be positive for lossy materials.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.AddLayer(Name, Thickness, Material)
+
+
Adds a new unpatterned layer with a specified thickness and material.
+

Usage:

+
S.AddLayer(Name = 'slab', Thickness = 0.6, Material = 'Silicon')
+
+
+

Arguments:

+
+
+
Name
+
(string) The name of the layer. Each layer should have a unique name if it is to be referenced later.
+
Thickness
+
(number) The thickness of the layer.
+
Material
+
(string) The name of the material which comprises the layer. With patterning, this is the default (background) material of the layer.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.AddLayerCopy(Name, Thickness, Layer)
+
+
Adds a new layer with a specified thickness, but identical patterning as another existing layer. +Note that this merely creates a reference to the copied layer; further patterning of the copied layer also affects the new layer. Additionally, a copy of a copy cannot be made.
+

Usage:

+
S.AddLayerCopy(Name = 'slab2', Thickness = 0.5, Layer = 'slab')
+
+
+

Arguments:

+
+
+
Name
+
(string) The name of the new layer, different from the layer being copied.
+
Thickness
+
(number) The thickness of the new layer.
+
Layer
+
(string) The name of the layer which whose pattern is to be copied. That layer cannot itself be a copy of a layer.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.SetLayerThickness(Layer, Thickness)
+
+
Updates an existing layer with a new thickness. +Previously cached layer eigenmodes are preserved, making this function the preferred way to update a layer’s thickness.
+

Usage:

+
S.SetLayerThickness(Layer = 'slab', thickness)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer to update.
+
Thickness
+
(number) The new thickness of the layer.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.RemoveLayerRegions(Layer)
+
+
Removes all layer regions from an existing layer.
+

Usage:

+
S.RemoveLayerRegions(Layer = 'slab')
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer to modify.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.SetRegionCircle(Layer, Material, Center, Radius)
+
+
Adds a (filled) circle of a specified material to an existing non-copy layer. +The circle should not intersect any other patterning shapes, but may contain or be contained within other shapes.
+

Usage:

+
S.SetRegionCircle(
+        Layer = 'slab',
+        Material = 'Vacuum',
+        Center = (0,0),
+        Radius = 0.2
+)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer to pattern. This layer cannot be a copy of another layer.
+
Material
+
(string) The name of the material which fills the interior of the circle.
+
Center
+
(pair of numbers) x- and y-coordinates of the center of the circle relative to the center of the unit cell (the origin).
+
Radius
+
(number) Radius of the circle.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.SetRegionEllipse(Layer, Material, Center, Angle, Halfwidths)
+
+
Adds a (filled) ellipse of a specified material to an existing non-copy layer. +The ellipse should not intersect any other patterning shapes, but may contain or be contained within other shapes.
+

Usage:

+
S.SetRegionEllipse(
+        Layer = 'slab',
+        Material = 'Vacuum',
+        Center = (0,0),
+        Angle = 30,            # in degrees
+        Halfwidths = (0.3,0.4) # semi-axis lengths
+)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer to pattern. This layer cannot be a copy of another layer.
+
Material
+
(string) The name of the material which fills the interior of the ellipse.
+
Center
+
(numeric table, length 2) x- and y-coordinates of the center of the ellipse relative to the center of the unit cell (the origin).
+
Angle
+
(number) The angle (in degrees) by which the x-axis of the ellipse should be rotated (CCW).
+
Halfwidths
+
(pair of numbers) The lengths of the semi-major axes of the ellipse. For an angle of 0, the first length is the semi-major axis in the x-direction, and the second length is the semi-major axis in the y-direction.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.SetRegionRectangle(Layer, Material, Center, Angle, Halfwidths)
+
+
Adds a (filled) rectangle of a specified material to an existing non-copy layer. +The rectangle should not intersect any other patterning shapes, but may contain or be contained within other shapes.
+

Usage:

+
S.SetRegionRectangle(
+        Layer = 'slab',
+        Material = 'Vacuum',
+        Center = (0,0),
+        Angle = 30,            # in degrees
+        Halfwidths = (0.3,0.4)
+)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer to pattern. This layer cannot be a copy of another layer.
+
Material
+
(string) The name of the material which fills the interior of the rectangle.
+
Center
+
(numeric table, length 2) x- and y-coordinates of the center of the rectangle relative to the center of the unit cell (the origin).
+
Angle
+
(number) The angle (in degrees) by which the x-axis of the rectangle should be rotated (CCW).
+
Halfwidths
+
(pair of numbers) The half-widths of the rectangle. For an angle of 0, the first length is half the width of the rectangle in the x-direction, and the second length is half the height in the y-direction.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.SetRegionPolygon(Layer, Material, Center, Angle, Vertices)
+
+
Adds a (filled) polygon of a specified material to an existing non-copy layer. +The polygon should not self-intersect nor intersect any other patterning shapes, but may contain or be contained within other shapes. The polygon must also be specified with positive orientation (the vertices circle CCW about an interior point).
+

Usage:

+
S.SetRegionPolygon(
+        Layer = 'slab',
+        Material = 'Vacuum',
+        Center = (0,0),
+        Angle = 10,            # in degrees
+        Vertices = (
+                (0,0),
+                (0.2,0),
+                (0.2,0.2),
+                (0.1,0.2),
+                (0.1,0.1),
+                (0,0.1)
+        )
+)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer to pattern. This layer cannot be a copy of another layer.
+
Material
+
(string) The name of the material which fills the interior of the polygon.
+
Center
+
(numeric table, length 2) x- and y-coordinates of the center of the polygon relative to the center of the unit cell (the origin).
+
Angle
+
(number) The angle (in degrees) by which the polygon should be rotated (CCW).
+
Vertices
+
(tuple of pairs) The x- and y-coordinates of the vertices of the (unrotated) polygon, one after another, in counter-clockwise order.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.SetExcitationPlanewave(IncidenceAngles, sAmplitude=0, pAmplitude=0, Order=0])
+
+
Sets the excitation to be a planewave incident upon the front (first layer specified) of the structure. +If both tilt angles are specified to be zero, then the planewave is normally incident with the electric field polarized along the x-axis for the p-polarization. +The phase of each polarization is defined at the origin (z = 0).
+

Usage:

+
S.SetExcitationPlanewave(
+        IncidenceAngles=(
+                10, # polar angle in [0,180)
+                30  # azimuthal angle in [0,360)
+        ),
+        sAmplitude = 0.707+0.707j,
+        pAmplitude = 0.707-0.707j,
+        Order = 0
+)
+
+
+

Arguments:

+
+
+
IncidenceAngles
+
(pair of numbers) Of the form (phi,theta) with angles in degrees. +phi and theta give the spherical coordinate angles of the planewave k-vector. +For zero angles, the k-vector is assumed to be (0, 0, kz), while the electric field is assumed to be (E0, 0, 0), and the magnetic field is in (0, H0, 0). The angle phi specifies first the angle by which the E,H,k frame should be rotated (CW) about the y-axis, and the angle theta specifies next the angle by which the E,H,k frame should be rotated (CCW) about the z-axis. +Note the different directions of rotations for each angle.
+
sAmplitude
+
(complex number) The electric field amplitude of the s-polarizations of the planewave.
+
pAmplitude
+
(complex number) The electric field amplitude of the p-polarizations of the planewave.
+
Order
+
(integer) An optional positive integer specifying which order (mode index) to excite. Defaults to 0. Refer to GetBasisSet() for details.
+
+
+

Return values:

+
+
None
+
+ +
+
+Simulation.SetFrequency(freq)
+
+
Sets the operating frequency of the system (and excitation).
+

Usage:

+
S.SetFrequency(1.2)
+
+
+

Arguments:

+
+
+
freq
+
(complex number) The frequency of the excitation. This is not the angular frequency (the angular frequency is 2pi times of this). +If a complex number is specified (typically for mode solving), the imaginary part should be negative for a physical (decaying in time) system.
+
+
+

Return values:

+
+
None
+
+ +
+
+

Outputs requiring no solutions

+
+
+Simulation.GetReciprocalLattice()
+
+
Retrieves the reciprocal lattice basis vectors. +The vectors lack the scaling by 2pi (multiply them by 2pi to obtain the true reciprocal lattice basis vectors).
+

Usage:

+
(Gu,Gv) = S.GetReciprocalLattice()
+
+
+

Arguments:

+
+
None.
+

Return values:

+
+
+
Gu, Gv
+
The first and second reciprocal lattice basis vectors. +Their relative geometric orientation is the same as the lattice specified in New(). +Each vector is a tuple of length 2, holding the x- and y-coordinates of the vector.
+
+
+
+ +
+
+Simulation.GetEpsilon(x, y, z)
+
+

Retrieves the dielectric constant at a particular point in the system by reconstructing the Fourier series using the G-vectors of the system.

+

Note that this reconstruction is not representative of the actual dielectric constant profile used in simulations (such a notion is not meaningful). The reconstruction is created using the closed-form Fourier series coefficients of the specified patterning, summed over the terms comprising the G-vector list obtained from lattice truncation. This function exists to provide an intuitive sense for the spatial resolution of a particular G-vector truncation order.

+
+

Usage:

+
eps = S.GetEpsilon(0.1, 0.2, 0.3)
+
+
+

Arguments:

+
+
+
x, y, z
+
(number) The coordinates of the point at which to retrieve the dielectric constant.
+
+
+

Return values:

+
+
+
eps
+
The (usually complex) relative dielectric constant at the specified point.
+
+
+
+ +
+
+Simulation.OutputLayerPatternPostscript(Layer[, Filename])
+
+
Outputs a list of PostScript commands to render the exact layer pattern description from the specified patterning commands. Assumes letter-sized paper.
+

Usage:

+
S.OutputLayerPatternPostscript(Layer = 'slab', Filename = 'out.ps')
+
+
+

Arguments:

+
+
+
Layer
+
(string) Name of the layer whose pattern description should be output.
+
Filename
+
(string, optional) Filename to which the description should be output. If this argument is not provided, standard output is used.
+
+
+

Return values:

+
+
None.
+
+ +
+
+

Outputs requiring solutions

+
+
+Simulation.OutputStructurePOVRay([Filename])
+
+
Outputs a POV-Ray script that will render one unit cell of the structure in 3D. Materials named air or vacuum (case insensitive) will be completely transparent. +Note that the output is not guaranteed to be correct or parsable by POV-Ray; it is only meant as a starting point to produce publication-ready figures.
+

Usage:

+
S.OutputStructurePOVRay(Filename = 'out.pov')
+
+
+

Arguments:

+
+
+
Filename
+
(string, optional) Filename to which the structure should be output. If this argument is not provided, standard output is used.
+
+
+

Return values:

+
+
None.
+
+ +
+
+Simulation.GetBasisSet()
+
+
Returns a tuple of reciprocal lattice coordinates of the Fourier series orders used. +The coordinates are in the reciprocal lattice basis, and so they are integers.
+

Usage:

+
Glist = S.GetBasisSet()
+
+
+

Arguments:

+
+
None.
+

Return values

+
+
+
Glist
+
A tuples of tuples of length 2 holding the pairs of integer recprical lattice coordinates.
+
+
+
+ +
+
+Simulation.GetAmplitudes(Layer, zOffset=0)
+
+
Returns the raw mode amplitudes within a particular layer. +For uniform (unpatterned) layers, the modes are simply the diffracted orders, and the indexing of the returned amplitudes corresponds to the value obtained from GetDiffractedOrder. +The first value is guaranteed to be the straight transmitted or specularly reflected diffraction order. +For patterned layers, there is typically no meaningful information in these amplitudes.
+

Usage:

+
(forw,back) = S.GetAmplitudes(Layer = 'substrate', zOffset = 0)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer in which to obtain mode amplitudes.
+
zOffset
+
(number) The z-offset at which to obtain the mode amplitudes.
+
+
+

Return values:

+
+
+
forw,back
+
Tuples of length 2*NumBasis containing the complex amplitudes of each forward and backward mode.
+
+
+
+ +
+
+Simulation.GetPowerFlux(Layer, zOffset=0)
+
+
Returns the integral of the power flux density over a unit cell surface normal to the z-direction. +In other words, the z-component of the integrated Poynting flux is returned.
+

Usage:

+
(forw,back) = S.GetPowerFlux(Layer = 'substrate', zOffset = 0)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer in which the integration surface lies.
+
zOffset
+
(number, optional) The z-offset of the integration surface from the beginning of the layer. This only matters for lossy layers.
+
+
+

Return values:

+
+
+
forw
+
The forward component of the complex Poynting vector. Note that the result is not time averaged (no factor of 0.5 multiplied in). The forward component is defined as (E_total^* x H_forw + H_total^* x E_forw) / 2, where E_forw and H_forw are the fields reconstructed from only the forward propagating waveguide modes of the layer.
+
back
+
The backward component of the complex Poynting vector. Note that the result is not time averaged (no factor of 0.5 multiplied in). An analogous definition of the backward component of the Poynting vector follows from above.
+
+
+
+ +
+
+Simulation.GetPowerFluxByOrder(Layer, zOffset=0)
+
+
Returns the integral of the Poynting flux density over a unit cell surface normal to the z-direction for each Fourier series order. +In other words, the z-component of the Poynting flux for each order is returned.
+

Usage:

+
P = S.GetPowerFluxByOrder(Layer = 'substrate', zOffset = 0)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer in which the integration surface lies.
+
zOffset
+
(number) The z-offset of the integration surface from the beginning of the layer. This only matters for lossy layers.
+
+
+

Return values:

+
+
+
P
+
A tuple with length equal to the number of Fourier series orders used. +Each entry of the is a pair (tuple) of forward and backward complex powers. +These power quantities are described in the section for GetPowerFlux().
+
+
+
+ +
+
+Simulation:GetStressTensorIntegral(Layer, zOffset=0)
+
+
Returns the integral of the electromagnetic stress tensor over a unit cell surface normal to the z-direction.
+

Usage:

+
(Tx, Ty, Tz) = S.GetStressTensorIntegral(layer, offset)
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer in which the integration surface lies.
+
zOffset
+
(number) The z-offset of the integration surface from the beginning of the layer.
+
+
+

Return values:

+
+
+
Tx,Ty,Tz
+
The real and imaginary parts of the x-, y-, and z-components of the stress tensor integrated over the specified surface, assuming a unit normal vector in the +z direction. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation.GetLayerVolumeIntegral(Layer, Quantity)
+
+
Returns the volume integral of a particular density over a unit cell throughout the entire thickness of a layer.
+

Usage:

+
I = S.GetLayerVolumeIntegral(Layer = 'slab', Quantity = 'U')
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer in which to integrate over.
+
Quantity
+

(string) The quantity to integrate. Currently, the choices are:

+
+
U
+
(epsilon*|E|^2 + |H|^2)
+
E
+
(epsilon*|E|^2)
+
H
+
(|H|^2)
+
e
+
(|E|^2)
+
+
+
+
+

Return values:

+
+
+
I
+
The complex integral of the density throughout the volume of the layer’s unit cell. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation:GetLayerZIntegral(Layer, xy)
+
+
Returns the line integral along z (depth direction) of the squared magnitudes of electric and magnetic field components (|Ex|^2, |Ey|^2, etc.) throughout the entire thickness of a layer.
+

Usage:

+
E,H = S.GetLayerZIntegral(Layer = 'slab', xy = (0.1, 0.2))
+
+
+

Arguments:

+
+
+
Layer
+
(string) The name of the layer in which to integrate through.
+
xy
+
(pair of numbers) The in-plane coordinates at which to integrate.
+
+
+

Return values:

+
+
+
E,H
+
Tuples of length 3 containing the x-, y-, and z-components of the integrated squared magnitude of the E or H field throughout the thickness of the layer. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation.GetFields(x, y, z)
+
+
Returns the electric and magnetic field at a particular point within the structure.
+

Usage:

+
(E,H) = S.GetFields(0.1, 0.2, 0.3)
+
+
+

Arguments:

+
+
+
x, y, z
+
(number) The coordinates of the point at which to obtain the field.
+
+
+

Return values:

+
+
+
E,H
+
Tuples of length 3 of the complex electric or magnetic field at the specified point. Note that the result is not time averaged (no factor of 0.5 multiplied in).
+
+
+
+ +
+
+Simulation.GetFieldsOnGrid(z, NumSamples, Format, BaseFilename)
+
+
Returns the electric and magnetic fields on a regular grid over the unit cell (fundamental parallelogram) at a particular z coordinate. +It is more efficient to use this function than GetFields().
+

Usage:

+
E,H = S.GetFieldsOnGrid(z = 0.2, NumSamples=(100,100), Format = 'Array')
+S.GetFieldsOnGrid(z = 0.2, NumSamples=(100,100), Format = 'FileWrite', BaseFilename = 'field')
+S.GetFieldsOnGrid(z = 0.2, NumSamples=(100,100), Format = 'FileAppend', BaseFilename = 'field')
+
+
+

Arguments:

+
+
+
z
+
(number) The z-coordinate of the plane on which to obtain the field.
+
NumSamples
+
(pair of integers) The number of sample points to use in each lattice vector direction.
+
Format
+

(string) Specifies the format of the output. Current choices are:

+
+
Array
+
Returns a pair of (tuple) arrays of dimension nu by nv, each element is a tuple of length 3, containing complex numbers of the E or H field components.
+
FileWrite
+
Outputs the field data to files, overwriting the files.
+
FileAppend
+
Outputs the field data to files, appending to the files. This is useful of volume fields are needed.
+
+
+
BaseFilename
+
(string) The base filename for file output. The outputs are named BaseFilename + '.E' and basefilename + '.H'.
+
+
+

Return values:

+
+
+
E,H
+
Only returned if format is ‘Array’. +Arrays (tuples) of dimension nu by nv, each element is a tuple of length 3, containing complex numbers of the E or H field components.
+
+
+
+ +
+
+Simulation.GetSMatrixDeterminant()
+
+
Returns the determinant of the S-matrix (scattering matrix) of the entire structure. +The determinant is an analytic function in the complex frequency plane and has poles at the complex modal frequencies of the system.
+

Usage:

+
(mant, base, expo) = S.GetSMatrixDeterminant()
+
+
+

Arguments:

+
+
None.
+

Return values:

+
+
+
mant
+
The determinant typically causes overflow or underflow, so it is returned as a mantissa multiplying a base raised to an exponent. The value of the determinant is mant*base^expo.
+
base
+
The base of the determinant representation (see above).
+
expo
+
The exponent of the determinant representation (see above).
+
+
+
+ +
+
+

Options

+
+
+Simulation.SetOptions(...)
+
+
Sets various options for a Simulation object. The options are described below, and any option not specified is left unchanged.
+

Usage:

+
S.SetOptions( # these are the defaults
+        Verbosity = 0,
+        LatticeTruncation = 'Circular',
+        DiscretizedEpsilon = False,
+        DiscretizationResolution = 8,
+        PolarizationDecomposition = False,
+        PolarizationBasis = 'Default',
+        LanczosSmoothing = False,
+        SubpixelSmoothing = False,
+        ConserveMemory = False
+)
+
+
+

Arguments:

+
+
+
Verbosity
+
(integer) The larger this value, the more status output is generated. Valid values are in the range of 0-9, inclusive. A value of 0 disables all status output.
+
LatticeTruncation
+

(string) Sets the type of lattice truncation to use when selecting G-vectors. Can be one of the following values:

+
+
Circular
+
This is the default. The G-vectors are selected to have shortest length (by l2 norm).
+
Parallelogramic
+
Chooses the G-vectors within a parallelogram aligned with the reciprocal lattice basis. The number chosen will always be a perfect square of an odd number.
+
+
+
DiscretizedEpsilon
+
(boolean) Enables or disables the use of discretization in generating the Fourier coefficients of the in-plane epsilon profiles, instead of using values from closed-form equations. When enabled, the coefficients are obtained by FFT.
+
DiscretizationResolution
+
(integer) This option only has an effect when DiscretizedEpsilon or SubpixelSmoothing are used. +This function sets the resolution of the FFT grid and vector field generated by PolarizationDecomposition. +The resolution is multiplied by the largest G-vector extent (integer lattice coordinate), and should be at least 2 to satisfy the Nyquist limit. It is best to use a number with small integer factors in order for the FFT to be computed efficiently. The size of each dimension of the FFT is obviously proportional to this value. The default is 8. +See the Fourier Modal Method formulations for details.
+
PolarizationDecomposition
+
(boolean) Enables or disables the use of proper in-plane Fourier factorization rules by decomposing fields into a polarization basis which conforms to the material boundaries. +The polarization basis field is generated automatically by computing a quasi-harmonic vector field everywhere tangent to the layer pattern boundaries. +This option is not guaranteed to work in the presence of tensor dielectric constants. +Enabling this feature typically improves convergence with respect to the number of G-vectors. +See the Fourier Modal Method formulations for details.
+
PolarizationBasis
+

(string) Sets the method by which the polarization decomposition basis is generated. +This option only has an effect when PolarizationDecomposition is set. +See the Fourier Modal Method formulations for details. +Valid choices are:

+
+
Default
+
Uses a smooth tangent vector field with respect to layer patterning.
+
Normal
+
Uses a unit normal vector field with respect to layer patterning.
+
Jones
+
Uses a complex-valued Jones polarization vector field.
+
+
+
LanczosSmoothing
+
(boolean or dict) A boolean value enables or disables smoothing of the Fourier series representations of the layer dielectric constants using the Lanczos sigma factor (box filtering). This reduces the Gibbs phenomenon ringing in the real space reconstruction. +Otherwise, specify a dictionary with keys Power (positive integer) and/or Width (positive number) to change the properties of the smoothing function.
+
SubpixelSmoothing
+
(boolean) Enables or disables the use of second-order accurate epsilon averaging rules within a pixel. +The average epsilon within a pixel is computed using the fill factor of each material and the interface direction. +Enabling this feature may improve convergence with respect to the number of G-vectors. +See the Fourier Modal Method formulations for details.
+
ConserveMemory
+
(boolean) Setting this option will prevent storage of certain intermediate results. This will save approximately 30% memory for non-trivial layers. +The drawback is slower computation of any output quantities that require solutions.
+
+
+

Return values:

+
+
None.
+
+ +
+
+

Miscellaneous

+
+
+Simulation.Clone()
+
+
Duplicates an existing Simulation object, copying all materials, layers, and excitation information. +No partial solution information is copied.
+

Usage:

+
S2 = S.Clone()
+
+
+

Arguments:

+
+
None.
+

Return values:

+
+
A copy of the Simulation object.
+
+ +
+
+
+ + +
+
+
+ +
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/search.html b/doc/build/html/search.html new file mode 100644 index 0000000..44659dd --- /dev/null +++ b/doc/build/html/search.html @@ -0,0 +1,128 @@ + + + + + + + + Search — S4 1.1 documentation + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Search

+
+ +

+ Please activate JavaScript to enable the search + functionality. +

+
+

+ From here you can search these documents. Enter your search + words into the box below and click "search". Note that the search + function will automatically search for all of the words. Pages + containing fewer words won't appear in the result list. +

+
+ + + +
+ +
+ +
+ +
+
+
+ +
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/searchindex.js b/doc/build/html/searchindex.js new file mode 100644 index 0000000..50a9100 --- /dev/null +++ b/doc/build/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({envversion:42,terms:{represent:[6,9],all:[1,2,4,6,7,8,9,10],code:3,partial:[6,9],rom:6,orthogon:6,queri:[6,1,3],lack:[6,1,9],numbasi:9,getepsilon:[4,6,9],squar:[8,6,9,3],lafay:3,extrapol:6,latter:7,legal:5,abil:3,setlayerthick:[6,9,3],setresolut:[6,10],follow:[6,5,1,9,10],solveinparallel:6,concaten:6,whose:[6,9],object:[0,4,1,7,3],accur:[6,9],depend:3,intermedi:[6,1,9],specif:[0,1],articl:5,shanhui:5,certainli:1,certain:[0,1,3,6,7,9],present:1,under:[8,1,2],sens:[4,6,9],norm:[6,9],adapt:6,merchant:2,sourc:[0,1],string:[6,9],without:[6,1,10,2,3],fals:[6,9],"01i":10,"01j":9,wigner:4,mpi:[6,7,3],ident:[6,9,3],volum:[0,5,6,9],intel:1,gfortran:1,veri:1,affect:[6,9,3],exact:[6,9],relev:8,common:[8,6],four:6,solver:[0,5,1,3],hyi:6,diffract:[6,1,9,3],list:[6,1,9,10,3],prefix:6,iter:4,getlayerzintegr:[6,9,3],"try":4,frecurs:[1,3],paralleliz:1,vector:[1,3,6,8,9,10],form:[6,9],getdiffractionord:[6,3],section:[6,9,10],small:[6,1,9],getlayerenergydensityintegr:6,freed:3,getlayerelectricenergydensityintegr:6,dimens:[6,9],upper:6,impli:2,erron:3,slower:[6,9],natur:8,subpixel:[6,10,3],direct:[4,6,9,3],e_forw:[6,9],getpowerfluxbyord:[6,9],past:4,range2:6,second:[6,9],cost:10,pass:[6,4,1,3],download:0,further:[6,9],suboptim:1,odd:[6,9],append:[6,9],victor:[0,5],excit:[8,6,9,10,3],index:[0,6,9],what:4,hide:1,appear:6,richard:2,eigenproblem:1,neg:[6,4,1,9],sum:[6,9],setregionrectangl:9,abl:8,brief:5,uniform:[6,9,3],current:[6,1,9,10,3],forw_r:6,version:[0,6,1,7,2],intersect:[6,1,9,3],h_total:[6,9],"new":[4,6,9,10,3],symmetr:1,"public":[5,4,9,2],thin:1,full:[1,10],deriv:2,iex:6,usag:[0,6,9],gener:[1,2,3,6,9,10],never:1,coeffici:[6,9,10],here:[8,6,1,9,10],disclaim:2,middl:10,liu20122233:5,ubuntu:7,along:[6,9,2],vertic:[6,9],modifi:[6,9,2],sinc:[8,4,1,9,10],valu:[6,4,1,9,3],trunc:6,box:[6,9],convert:[6,3],conta:6,convers:[8,6],setfrequ:[8,6,9,10],libc:2,xy_i:6,larger:[6,9],setlatticetrunc:[6,10,3],converg:[6,1,9,3],xy_r:6,spectrumsampl:[0,1,3],newsimul:[6,9,10],yield:6,within:[6,4,1,9],real:[6,1,9,3],extrem:0,chang:[6,9,3],fourier:[0,1,3,4,5,6,9],mix:3,magnitud:[6,9],commonli:1,slab2:9,scale:[8,6,9],regardless:[8,3],repositori:[0,1],txi:6,readabl:1,modul:[0,1],mantr:6,prefer:[4,5,6,7,9,10],layer:[0,1,3,4,5,6,9,10],setregionpolygon:9,volt:8,unix:1,api:[0,1],instabl:4,instal:[0,1],total:[4,6],txr:6,unit:[0,4,6,9,3],highli:7,plot:6,quasi:[6,9],from:[0,4,1,3],describ:[6,9],would:[8,4,1,3],memori:[6,1,9,7,3],eyi:6,univers:2,upgrad:3,next:[6,9,7],few:3,formul:[0,1,3,4,6,7,9],call:[0,6,1,10,7],recommend:[4,1,10,7],taken:2,dict:9,jonathan:2,type:[6,1,9],minor:3,more:[1,2,5,6,9,10],sort:2,desir:[6,10],forc:6,y2_1:6,y2_2:6,line:[0,6,1,9,3],warn:[1,3],flag:[1,7],olivi:3,accept:6,particular:[6,1,9,2],git:7,hold:[6,1,9],effort:1,cach:[6,1,9,3],must:[6,1,9],permitt:[8,6,9],none:[10,6,9,7],retriev:[6,9,3],left:[1,9],azimuth:9,work:[10,6,9,2],uniqu:[6,9],dev:7,remain:[6,1],itself:[6,9],obvious:[5,6,9],can:[4,1,3],tabul:4,uselanczossmooth:6,purpos:2,root:8,scatter:[6,9],control:[6,10],setverbos:6,wang:3,give:[6,9],superposit:6,share:[1,7],xz_r:6,templat:1,topic:4,critic:3,minimum:7,bend:6,tab:1,also:[0,1,2,3,6,9,10],parsabl:9,sharp:6,standard:[6,1,9],occur:6,concept:6,alwai:[6,4,1,9,10],surfac:[6,9],cours:2,end:[6,1],divid:1,programmat:1,anoth:[6,9],write:[4,6,2],criterion:6,sever:[6,3],instead:[8,6,1,9],simpl:1,sin:6,circular:[6,9,10,3],suffer:4,everywher:[6,9],product:6,msy:1,referenc:9,algebra:1,numsampl:9,clone:[6,9,7],after:[6,9],yy_r:6,reflect:[8,0,6,9],befor:7,wrong:[4,3],plane:[6,9,10,3],distort:6,usejonesvectorbasi:[6,10],addlayercopi:[6,9,10],mai:[1,2,4,6,9,10],multipl:[8,6],formuat:4,data:[6,4,1,9,3],parallel:[6,1,7,3],physic:[8,0,5,6,9],harmon:[6,9],alloc:[1,3],github:0,domin:10,s4_destroysolut:3,johnson:2,interpol:[0,4,1,3],ani:[5,6,9,2],bind:[0,5,1],issn:5,correspond:[8,6,4,1,9],ghz:6,predic:[1,2],caus:[6,1,9,3],rather:1,"switch":[6,3],rectangular:3,environ:[6,1],spheric:[6,9],allow:[6,1,7],enter:10,e_tot:[6,9],fan:[0,5],first:[4,6,9],order:[6,4,1,9,3],quantiti:[6,4,1,9],superscript:[5,4],origin:[0,4,6,9,2],level:[6,9],sciencedirect:5,rotat:[6,9,3],softwar:[5,2],eps_r:6,offici:1,fft:[1,2,3,4,6,7,9],becaus:[8,6],filewrit:[6,9],paper:[5,6,9],through:[6,9],incid:[8,6,9,10,3],equival:[1,9],kottk:3,still:[10,2],mainli:[6,1],dynam:1,paramet:[4,1,3],perfect:[6,9],polarizationbasisoversamplingfactor:3,style:1,group:0,thank:3,fit:2,binari:0,chosen:[6,9],fix:[1,7,3],outputlayerpatternpostscript:9,hzi:6,usenormalvectorbasi:[6,10],kiss_fft:[1,3],platform:1,window:[1,7],drawback:[6,9],decai:[6,9],stephen:2,main:1,might:[8,5],easier:0,reli:4,them:[6,9,3],good:10,"return":[6,1,9,3],greater:3,thei:[6,1,9],halv:3,python:[0,1,7,3],safe:1,valarrai:6,back_r:6,rectangl:[6,9],disabl:[6,1,9,3],band:[1,3],conquer:1,kiss:[1,2,3],half:[6,9],f_start:6,now:[10,3],align:[6,1,9,3],nor:[5,6,9],xx_i:6,choic:[10,6,9,7],term:[6,9,2],opaqu:1,addmateri:[6,10],name:[6,1,9],lanczo:[6,9,3],main_lua:1,drop:3,latticetrunc:9,loadstr:6,separ:[4,7],easili:9,achiev:9,mingw:1,mode:[6,9,10],compris:[6,9],each:[6,9,10,3],found:6,outputlayerpatternr:[4,6],xx_r:6,electr:[8,0,6,9],errata:1,truncat:[6,9,10,3],mean:1,clamp:6,domain:[0,2],detect:[1,3],citat:5,stratifi:0,hard:1,idea:1,realli:6,heavi:1,redistribut:2,"static":[1,3],expect:6,year:5,fine:[6,1],wavelength:8,energi:6,differ:[6,1,9,10,3],orient:[6,9],special:[1,3],out:[6,9],variabl:6,magnet:[6,9],shown:6,safeti:1,matrix:[0,6,1,9,3],contigu:1,space:[6,1,9],gradient:1,from_unit:6,getfrequ:6,parallelogram:[6,9],hyr:6,publish:[0,10,2],your:2,footnot:10,specularli:[6,9],clockwis:9,rel:[6,1,9],lattic:[1,3,6,8,9,10],print:[6,10],size:[8,6,1,9],ref:5,correct:[5,4,1,9],matric:[1,3],cosin:6,linear:[8,0,6,1],exterior:6,written:2,pleas:6,manipul:[6,1],infin:4,free:[5,2,3],templ:2,setregioncircl:9,reason:10,base:[8,4,6,9,10],dictionari:9,usual:[9,10],invas:1,org:[5,2],"byte":3,usesubpixelsmooth:[6,10],featur:[3,4,6,7,9,10],shortest:[6,9],basi:[6,9,10,3],precompil:1,zx_r:6,extend:4,indent:1,convent:3,thread:[6,1,7],angl:[8,6,9],frequenc:[0,1,3,4,6,9,10],submitresult:6,ask:5,mac:7,p_amp:6,silicon:[9,10],length:[0,6,1,9],enforc:5,place:[6,2],due:[8,1,3],outsid:4,s4lua:7,retain:6,zx_i:6,principl:10,confus:8,top:[6,1,9,10],integrand:6,oper:[6,9,10],usediscretizedepsilon:[6,10],ihx:6,zz_i:6,yy_i:6,directli:[6,1],prevent:[6,9],transform:[4,1,3],wave:0,independ:6,number:[1,3,5,6,7,8,9,10],rank:6,system:[6,9],restrict:2,ihi:6,done:6,construct:1,symmetri:[6,1],blank:[6,9,10],thick:[4,6,9,10,3],custom:[1,7],miss:[6,3],angular:[6,9],zz_r:6,gpl:2,given:[6,1],singular:1,kochanek:6,script:[10,4,6,9,2],yz_i:6,licens:0,setbasisfielddumpprefix:6,sometim:8,least:[6,9],libsuitespars:7,yz_r:6,fmm:[0,4,1,7],overhead:1,averag:[6,9],circl:[6,9,10],similarli:4,termin:[6,10],fftw3:[1,7],"final":10,store:3,setexcitationexterior:6,shell:10,yx_r:6,option:[1,7,2,3],rusti:2,especi:1,tool:6,copi:[10,4,6,9,2],outputstructurepovrai:[6,9],specifi:[1,4,6,8,9,10],task:1,openbla:[1,7],part:[6,9,10,3],layernam:6,mostli:1,fall:2,off:[8,3],grace:1,yx_i:6,mechan:10,wide:1,newspectrumsampl:6,conveni:[6,1],overwrit:[6,9],range1:6,provid:[1,4,6,7,8,9],gethfield:6,remov:[6,9],zero:[6,4,1,9],structur:[5,3],quasiharmon:1,project:2,matter:[6,1,9],bandsolv:1,setexcitationplanewav:[6,9,10,3],light:8,posit:[6,9],toward:4,ccw:[6,9],seri:[6,9,10],pre:1,result_list:6,rad:6,counter:9,comput:[5,4,1,3],seitz:4,boston:2,maxev:6,p_phase:6,argument:[6,1,9,10],rai:[6,9],raw:[6,9,3],mater:[6,9],width:[6,1,9,3],manner:6,have:[1,2,3,4,6,8,9],tabl:4,need:[1,3,4,6,7,9],seem:3,element:[6,9],slab:[9,10],packag:[0,5,1],maxwel:[8,0],engin:0,dieletr:6,lib:7,inform:[6,1,9,10],check:4,self:[6,1,9],thorough:1,accuraci:10,note:[6,1,9,2],liu:[0,5],discret:[6,1,9,3],take:[6,3],which:[1,4,5,6,8,9,10],epsilon:[4,6,9],interior:[6,9],singl:[6,9,3],even:[2,3],begin:[6,9],backward:[6,9],unless:10,"707j":9,trace:3,initialnumpoint:6,multipli:[6,9],previou:[6,3],reach:1,most:[6,1],tilt:[6,9],regular:[6,1,9,3],dielectr:[6,1,9,10,3],plan:10,letter:[6,9],mpirank:[6,3],watt:8,electromagnet:[0,5,6,9],segment:[6,3],why:4,tyr:6,original_nam:6,latex:4,lapackthreadtest:1,doi:5,don:4,url:5,later:[1,9,2],metal:3,doe:[6,4,1,10,3],bibtex:5,runtim:2,determin:[8,6,1,9,10],polarizationdecomposit:9,built:[6,1,9],isdon:6,axi:[6,9],sigma:[6,9],forw_i:6,meaning:[6,9],phenomenon:[6,9],removelayerregion:9,show:8,verbos:9,speedup:7,radiu:[6,9,10],"3x3":9,unchang:9,bartel:6,frontend:[0,10,7,3],freeli:[5,2],trivial:[6,1,9],find:[10,2],involv:6,absolut:[8,5,6],onli:[6,4,1,9,3],iez:6,locat:[4,6,9,7],copyright:0,lua:[0,1,2,3,4,7],"true":[6,9],relativeerror:6,solut:[1,3],state:[6,9],zgeev:1,than:[6,1,9],iei:6,experiment:6,suppos:8,factor:[8,6,9],nyquist:[6,9],analyt:[4,6,9],local:[0,3],over:[6,4,1,9],hope:[5,2],meant:9,getamplitud:[6,9,3],cube:[6,9],variou:[6,1,9],get:6,air:[6,9],express:6,obtain:[0,1,3,6,7,9,10],receiv:2,cannot:[6,9],exempt:1,usepolarizationdecomposit:[6,10],increas:4,reconstruct:[6,9],bug0061:1,straightforwardli:1,requir:[0,1,7],numalloc:1,shewchuk:2,h_forw:[6,9],zy_i:6,enabl:[6,1,9,3],densiti:[6,9],possibl:[6,1,10],freqr:6,intrins:8,method:[0,3,5,6,7,9],cleanli:1,bad:1,eps_i:6,addtion:1,integr:[0,6,9,3],freqi:6,contain:[1,2,6,7,9,10],zy_r:6,anisotrop:[10,3],where:[8,6,4,1,9],analog:[6,9],catmul:6,conform:[6,1,9],set:[1,4,6,7,8,9,10],dump:6,intuit:[6,9],getsmatrixdetermin:[6,9],frame:[6,9],discretizationresolut:9,decompos:[6,9],uselessmemori:[6,3],see:[10,6,9,2],bare:7,result:[1,3,6,7,9,10],rangethreshold:6,arg:6,reserv:1,close:[6,9],stack:[1,3],charact:1,improv:3,best:[6,1,9,10],infinit:[4,10],polymorph:1,statu:[6,9],to_unit:6,tensor:[6,9,3],correctli:[4,10],freq:[6,9],pattern:[0,1,3,4,6,9,10],boundari:[6,9],below:[10,6,9,7],tend:1,copyleft:2,linearsolv:3,getspectrum:6,repeat:[1,3],between:[8,6,1,3],theta:[6,9,10],neither:5,freqlist:6,speed:[8,1,10],kindli:5,altern:0,ken:3,discretizedepsilon:9,kei:[6,9],web:2,numer:[1,3,4,6,9,10],filter:[6,9,3],were:[2,3],liblua5:7,stress:[6,9],entir:[6,9],eigenmod:[6,9,3],unrot:[6,9],extent:[6,9],otherwis:[6,1,9,10],"2pi":[6,9],zoffset:9,micron:8,addit:[10,9,2,3],both:[6,1,9,3],last:[4,6],setmateri:[6,9],extens:[0,1,3,6,7,9,10],spectra:[8,0,6],howev:[8,4,1,10],ignor:[6,1],valgrind:3,against:1,etc:[8,6,9],tutori:0,equat:[8,0,6,9],context:3,logic:8,tangent:[6,9],didact:10,com:[5,7],ellips:[6,9],suggest:7,unclear:1,planewav:[8,6,9,10,3],author:5,figur:[8,9],eigenfunct:6,conjug:1,format:[5,6,9],s0010465512001658:5,height:[6,9],solv:[8,0,6,1,9],pole:[6,9],uniniti:3,s_phase:6,xz_i:6,suppli:1,respect:[6,9],getreciprocallattic:[6,9],throughout:[0,6,9],assum:[4,6,9,10],subtabl:6,setlayerpatternrectangl:6,math:6,enablepolarizationdecomposit:6,halfwidth:[6,9],ultim:9,becom:1,evalu:6,coupl:0,fortran:[1,3],addition:[6,9],underflow:[6,9],numpi:9,invers:8,atla:1,mark:2,compon:[0,1,3],eps_tensor:6,much:[9,3],newinterpol:6,threshold:[6,1],modif:[1,2],setlattic:[6,10,3],dure:6,field:[0,1,3,4,6,8,9,10],incidenceangl:9,setopt:9,presenc:[6,9],hzr:6,commun:[0,5],search:0,unnecessarili:1,spectrum:[5,6],multithread:3,coordin:[0,4,6,9],lift:1,eigensolv:3,func:6,input:[6,1],mant:9,rang:[6,9],those:[4,6],"case":[4,6,9,10,3],replic:10,multi:7,save:[6,9],sit:1,gnu:2,s_amp:6,straight:[6,9],properti:9,borgerd:2,empti:6,"618nm":8,aim:6,defin:[6,4,1,9,10],calcul:3,quak:2,ought:1,behavior:6,error:6,suffici:[4,1],region:9,loop:4,pack:0,propag:[6,9],planar:0,tzr:6,insensit:[6,9],file:[4,6,9,2],cell:[8,4,6,9,3],almost:1,therefor:8,site:2,equal:[6,9],getstresstensorintegr:[6,9],s4_pyext:7,scipi:9,contract:6,substanti:1,pthread:1,tzi:6,crash:3,exi:6,mani:1,routin:[6,1,2],outputlayerpatterndescript:6,pointer:1,scienc:5,uniti:8,incompat:[1,3],irrelev:[8,4,10],clearli:6,minim:[6,9],perform:[8,6,1,9,3],tidi:3,make:[0,6,9,7],addlay:[6,9,10],fileappend:[6,9],cross:[6,3],same:[6,9,3],"while":[6,9],hxr:6,add:[6,9,10],html:2,largest:[6,9],algorithm:[0,5,1],document:3,samplitud:9,complex:[6,1,9],overzeal:3,complet:[6,9],disc:10,incorrect:3,phi:[8,6,9,10],http:[5,7,2],time:[0,1,3,6,9,10],nil:6,imagin:8,optim:0,expans:[6,9],upon:[6,9],effect:[6,1,9,3],hand:1,rais:[6,9],temporari:1,initi:[6,3],poynt:[6,9],extern:1,robust:1,setlayerpatterncircl:[6,10],typic:[8,6,9,7],tune:1,recreat:3,unpattern:[6,9],lower:6,appropri:1,kept:1,thz:[8,6],incorpor:4,thu:6,cpp:[1,3],well:[0,1,10,2],inherit:1,non:[6,1,9,3],permeabl:8,exampl:[0,4,6,7,2],command:[6,9,7,3],thi:[0,1,2,3,4,5,6,7,8,9,10],choos:[8,6,9],undefin:6,roughli:[6,9],eigenvalu:1,latest:[0,7],comment:1,lossi:[6,9],s4_free:3,just:[6,7],less:6,entri:[6,9],ipair:6,ordin:6,insid:10,front:[6,9],shape:[4,6,9,3],behind:1,depart:0,glue:1,recpric:[6,9],languag:[6,1],previous:[6,9],expon:[6,9],struct:1,pamplitud:9,lapack:3,workspac:[1,3],point:[4,6,9,3],makefil:7,except:[1,7],theoret:1,paral:6,pov:[6,9],getlayervolumeintegr:9,other:[6,1,9],implement:[0,1,10,7],sampler:6,compat:1,f_end:6,distinguish:6,subsequ:6,approxim:[6,9],match:6,build:[1,7],opt:6,applic:3,vendor:1,around:1,transpar:[6,9],preserv:[6,9],foundat:2,varieti:1,load:2,amd:1,numg:[6,9],period:[0,3,4,5,6,8,9,10],imaginari:[6,9,3],transmit:[6,9,10],grid:[6,9,3],background:[6,9],vacuum:[8,6,9,10],bit:7,rnp:1,python3:7,hxi:6,cubic:[6,3],measur:8,setnumg:[6,10],getbasisset:9,like:1,semi:[6,9,10],header:1,should:[6,4,1,9,2],ring:[6,9],arbitrari:6,therebi:2,pol:[6,10],integ:[6,1,9],edit:7,"boolean":[6,9],necessari:[8,5],either:[6,1,7,2],output:[4,1,3],setlayerpatternellips:6,pair:[6,9],page:[0,5,2],two:[6,7,3],"function":3,node:6,www:[5,2],old:[6,1],deal:1,simplifi:10,eyr:6,arrai:[6,9,3],interact:[6,10],some:[8,4,1,3],back:[6,9,3],ezr:6,resolv:[6,3],global:0,pariti:9,intern:[0,6,1,9],tyi:6,epsilon_inv:3,ezi:6,proper:[6,1,9,10],guarante:[4,6,9],processor:6,getnumg:6,librari:[0,1,7,2],distribut:[10,1,7,2],pixel:[6,9],render:[6,9],hermit:[6,3],mlp1:3,bottom:10,flux:[6,9,10],avoid:1,normal:[8,6,9,10,3],proport:[6,9],per:[8,1],summar:10,when:[8,6,1,9,3],dofil:4,estim:6,larg:[6,4,1,10],select:[6,1,9,10,3],clarif:2,expo:[6,9],aaswath:3,posix:7,oversampl:6,refer:[0,5],machin:[6,1,7],libfftw3:7,investig:1,run:[1,10,7,3],power:[0,6,9,10],word:[6,9],journal:5,manti:6,duplic:[6,9,3],getlayermagneticenergydensityintegr:6,great:1,although:[4,1],offset:[6,9],major:[6,9],appli:2,geometr:[6,1,9],ihz:6,gauthier:3,convertunit:[6,3],about:[6,9,10],getfieldsongrid:9,actual:[6,4,1,9],usa:2,column:1,materi:[4,6,9,10,3],povrai:4,literatur:10,simul:[0,1],degre:[6,9,10],statement:6,issu:3,modal:[0,5,6,9],simpli:[0,4,6,9],rigor:0,produc:[6,9],block:[1,3],peak:6,compil:[0,1,3],effici:[6,1,9,3],amplitud:[0,6,9,10,3],conservememori:9,satisfi:[6,9],handl:[1,10],basenam:6,getglist:6,bound:6,automat:[6,4,1,9],compos:[0,1],warranti:2,phase:[6,9,10,3],hermitian:1,cholmod:3,been:[6,10,3],absoluteerror:6,ensur:1,"import":6,updat:[6,9],announc:3,storag:[6,9],mere:[6,9],inclus:[6,9],fast:10,rcwa:[0,1,3],pcall:6,wai:[6,4,1,9,10],area:3,abov:[6,9],getdiffractedord:[6,9],support:[0,1,3,6,7,10],mkl:1,primari:[6,9],submit:6,center:[4,6,9,10],avail:[5,1,3],start:[6,4,1,9],adjac:6,plain:1,interfac:[6,1,9,3],low:6,suit:2,forward:[6,9,10],maxbend:6,strictli:10,interv:6,analysi:0,media:10,respositori:7,medium:10,gibb:[6,9],interest:1,getfieldplan:6,enough:6,mantissa:[6,9],tupl:9,minimumspac:6,basic:0,includ:[4,9,10],decomposit:[6,1,9],substrat:9,back_i:6,link:1,translat:[8,3],overflow:[6,9],stand:0,forw:[6,9],bug:[7,3],faster:3,"680nm":8,cubatur:2,made:[6,9,10],furthermor:1,stanford:[0,2],whether:[6,1],s4_simul:3,spatial:[4,6,9,3],smooth:[0,6,9,3],maximum:[6,1,9],slow:[1,10],primarili:1,amcl:1,limit:[6,9],getefield:6,fundament:[6,9],sampl:[4,6,9],problem:[1,3],eigenvector:3,pii:5,waveguid:[6,9],reciproc:[6,9],constant:[6,9,10],creat:[6,9],getfield:[6,9],flow:[1,10],vertex_count:6,filenam:[6,9],textbook:1,repres:[6,1,9],setlayerpatternpolygon:6,postscript:[6,9],exist:[6,1,9],setregionellips:9,request:[6,9,3],typeset:4,russel:2,happen:[4,1],fill:[6,9],assembl:1,diagnost:6,readi:9,polygon:[6,9,3],gnuplot:6,mpisiz:[6,3],titl:5,user:[1,10,2],nan:3,detail:[6,1,9,2],invalid:1,"default":[6,4,1,9,3],valid:[6,9],futur:6,jone:[6,9,10],lanczossmooth:9,test:[1,3],exr:6,you:[10,5,4,7,2],transmiss:[8,0,5,6,10],blp1:3,poor:10,polar:[1,3,6,8,9,10],resolut:[6,9,10,3],y1_2:6,y1_1:6,fulli:[9,10],subdivid:6,"class":[6,9],have_mpi:3,vertex:6,getpowerflux:[6,9,10],definit:[6,1,9],intens:6,glist:9,consid:[8,2],ccan:2,absorpt:0,outputpatterndescript:3,uniformli:6,debian:7,serial:6,subdivis:6,reduc:[8,6,1,9,10],setlay:6,invari:8,spline:[6,3],polarizationbasi:9,getlayerelectricfieldintensityintegr:6,abscissa:6,directori:[1,10,2],cpc:5,descript:[5,6,9],visual:6,rule:[6,9],notion:[6,9],tricki:4,victorliu:7,depth:[6,9],basefilenam:[6,9],subpixelsmooth:9,leak:3,spectral:6,polbasisvl:3,profil:[6,1,9,10],inc:2},objtypes:{"0":"lua:module","1":"lua:function","2":"lua:method","3":"lua:class","4":"lua:data","5":"py:module","6":"py:method","7":"py:function","8":"py:class"},objnames:{"0":["lua","module","Lua module"],"1":["lua","function","Lua function"],"2":["lua","method","Lua method"],"3":["lua","class","Lua class"],"4":["lua","data","Lua data"],"5":["py","module","Python module"],"6":["py","method","Python method"],"7":["py","function","Python function"],"8":["py","class","Python class"]},filenames:["index","dev_info","license","changelog","faq","citing","lua_api","install","units","python_api","tutorial"],titles:["Introduction to S4","Developer Info","License and Copyright","Changelog","Frequently Asked Questions","How to cite","Lua API reference","Download & Installation","Units & Coordinates","Python API reference","Tutorial"],objects:{"":{S4:[9,5,0,"-"]},"S4.Simulation":{SetExcitationPlanewave:[9,6,1,""],GetSMatrixDeterminant:[9,6,1,""],GetReciprocalLattice:[9,6,1,""],GetAmplitudes:[9,6,1,""],GetEpsilon:[9,6,1,""],GetBasisSet:[9,6,1,""],SetFrequency:[9,6,1,""],SetRegionCircle:[9,6,1,""],AddLayer:[9,6,1,""],GetFieldsOnGrid:[9,6,1,""],Clone:[9,6,1,""],SetLayerThickness:[9,6,1,""],SetRegionRectangle:[9,6,1,""],GetPowerFluxByOrder:[9,6,1,""],GetLayerVolumeIntegral:[9,6,1,""],RemoveLayerRegions:[9,6,1,""],SetMaterial:[9,6,1,""],GetPowerFlux:[9,6,1,""],SetRegionEllipse:[9,6,1,""],AddLayerCopy:[9,6,1,""],OutputLayerPatternPostscript:[9,6,1,""],SetRegionPolygon:[9,6,1,""],SetOptions:[9,6,1,""],OutputStructurePOVRay:[9,6,1,""],GetFields:[9,6,1,""]},S4:{"Simulation:GetReciprocalLattice":[6,2,1,""],"Simulation:SetNumG":[6,2,1,""],"Simulation:UseNormalVectorBasis":[6,2,1,""],"Simulation:UsePolarizationDecomposition":[6,2,1,""],NewInterpolator:[6,1,1,""],NewSpectrumSampler:[6,1,1,""],"Simulation:UseDiscretizedEpsilon":[6,2,1,""],arg:[6,4,1,""],Integrate:[6,1,1,""],"SpectrumSampler:GetFrequency":[6,2,1,""],"Simulation:SetBasisFieldDumpPrefix":[6,2,1,""],"Simulation:UseLessMemory":[6,2,1,""],"SpectrumSampler:SubmitResult":[6,2,1,""],"Simulation:GetSMatrixDeterminant":[6,2,1,""],"SpectrumSampler:GetFrequencies":[6,2,1,""],NewSimulation:[6,1,1,""],"Simulation:SetMaterial":[6,2,1,""],"Simulation:GetFieldPlane":[6,2,1,""],"Simulation:SetLayerPatternCircle":[6,2,1,""],"Simulation:SetExcitationPlanewave":[6,2,1,""],"SpectrumSampler:IsDone":[6,2,1,""],"Interpolator:Get":[6,2,1,""],"Simulation:GetLayerZIntegral":[6,2,1,""],"Simulation:SetLattice":[6,2,1,""],Interpolator:[6,3,1,""],"Simulation:GetFields":[6,2,1,""],"Simulation:AddLayer":[6,2,1,""],"Simulation:SetExcitationExterior":[6,2,1,""],SolveInParallel:[6,1,1,""],"Simulation:SetLayerPatternEllipse":[6,2,1,""],"Simulation:SetFrequency":[6,2,1,""],"Simulation:SetResolution":[6,2,1,""],"Simulation:GetDiffractionOrder":[6,2,1,""],"Simulation:GetLayerElectricFieldIntensityIntegral":[6,2,1,""],"Simulation:OutputLayerPatternRealization":[6,2,1,""],"Simulation:Clone":[6,2,1,""],"Simulation:AddLayerCopy":[6,2,1,""],"Simulation:GetEpsilon":[6,2,1,""],"Simulation:AddMaterial":[6,2,1,""],"Simulation:GetStressTensorIntegral":[6,2,1,""],"Simulation:GetLayerEnergyDensityIntegral":[6,2,1,""],"Simulation:GetLayerMagneticEnergyDensityIntegral":[6,2,1,""],"Simulation:GetNumG":[6,2,1,""],Simulation:[9,8,1,""],"Simulation:OutputStructurePOVRay":[6,2,1,""],"Simulation:GetPowerFlux":[6,2,1,""],"Simulation:UseSubpixelSmoothing":[6,2,1,""],MPISize:[6,4,1,""],"Simulation:SetVerbosity":[6,2,1,""],"Simulation:GetHField":[6,2,1,""],"Simulation:SetLayerThickness":[6,2,1,""],"Simulation:SetLayerPatternPolygon":[6,2,1,""],"Simulation:GetLayerElectricEnergyDensityIntegral":[6,2,1,""],SpectrumSampler:[6,3,1,""],"Simulation:SetLayer":[6,2,1,""],"Simulation:GetAmplitudes":[6,2,1,""],New:[9,7,1,""],"Simulation:GetEField":[6,2,1,""],"SpectrumSampler:SubmitResults":[6,2,1,""],"Simulation:UseLanczosSmoothing":[6,2,1,""],"Simulation:GetGList":[6,2,1,""],ConvertUnits:[6,1,1,""],"Simulation:GetPowerFluxByOrder":[6,2,1,""],"Simulation:OutputLayerPatternDescription":[6,2,1,""],"Simulation:SetLayerPatternRectangle":[6,2,1,""],MPIRank:[6,4,1,""],"Simulation:UseJonesVectorBasis":[6,2,1,""],"SpectrumSampler:GetSpectrum":[6,2,1,""],"Simulation:SetLatticeTruncation":[6,2,1,""]}},titleterms:{compil:7,program:1,code:1,auxilliari:1,repositori:7,api:[6,9],question:4,modul:9,indic:0,packag:7,cholmod:1,structur:1,tabl:0,download:7,comput:0,simul:[6,9],port:1,librari:6,paramet:[6,9],content:0,what:0,from:7,miscellan:[6,9],convent:1,area:1,lapack:1,licens:2,frequenc:8,solut:[6,9],compon:2,lua:6,tutori:10,unit:8,basic:10,binari:7,formul:10,document:0,instal:7,cite:5,refer:[6,9],"function":1,sourc:7,option:[6,9],power:8,python:9,sup:0,usag:10,amp:[8,7],how:5,fftw:1,amplitud:8,improv:1,releas:0,develop:1,method:10,requir:[6,9],introduct:0,info:1,github:7,copyright:2,specif:[6,9,2],coordin:8,bla:1,fourier:10,changelog:3,ask:4,object:[6,9],exampl:10,length:8,spectrumsampl:6,can:0,modal:10,time:8,output:[6,9],interpol:6,frequent:4,depend:[1,7]}}) \ No newline at end of file diff --git a/doc/build/html/tutorial.html b/doc/build/html/tutorial.html new file mode 100644 index 0000000..3460c86 --- /dev/null +++ b/doc/build/html/tutorial.html @@ -0,0 +1,307 @@ + + + + + + + + Tutorial — S4 1.1 documentation + + + + + + + + + + + + + + + +
+
+
+
+ +
+

Tutorial

+
+

Basic Usage

+

This section assumes that the Lua frontend is used. +The program may be run with a Lua script as an argument, in which case the script is run and then the program terminates, or without an argument, in which case it enters interactive mode with a Lua shell.

+

The basic flow of a script is listed below. +To find more information about these functions and for a full listing, see the Lua API reference.

+
    +
  1. Obtain a new simulation object:

    +
    S = S4.NewSimulation()
    +
    +
    +

    S now contains a simulation object with a blank specification, and no solutions.

    +
  2. +
  3. Set the lattice and number of basis functions:

    +
    S:SetLattice({ux,uy}, {vx,vy})
    +S:SetNumG(100)
    +
    +

    This sets the periodicity based on the lattice vectors (ux,uy) and (vx,vy). +The number of basis functions is set to 100.

    +
  4. +
  5. Define all materials:

    +
    S:AddMaterial('Vacuum', 1)
    +S:AddMaterial('Silicon', {12, 0.01})
    +
    +

    This adds a material called “Vacuum” with a dielectric constant of 1, and a material called “Silicon”, with a dielectric constant of 12+0.01i.

    +
  6. +
  7. Add all layers:

    +
    S:AddLayer('top', 0, 'Vacuum')
    +S:AddLayer('slab', 0.5, 'Silicon')
    +S:AddLayerCopy('bottom', 0, 'top')
    +
    +

    Here we are adding a semi-infinite Vacuum layer (the thickness is largely irrelevant), a middle slab layer made of silicon with a thickness of 0.5, and finally a bottom semi-infinite layer that is a copy of the top layer. +It is always preferable to copy layers if possible since it reduces the computational cost.

    +
  8. +
  9. Add patterning to layers:

    +
    S:SetLayerPatternCircle('slab',   -- layer to pattern
    +                        'Vacuum', -- material inside circle
    +                        {0,0},    -- center of circle
    +                        0.2)      -- radius of circle
    +
    +
  10. +
  11. Specify the excitation mechanism:

    +
    S:SetExcitationPlanewave(
    +        {0, 0}, -- phi in [0,180), theta in [0,360)
    +        {1, 0}, -- s-polarization amplitude and phase in degrees
    +        {0, 0}) -- p-polarization
    +
    +

    This sets the excitation to a normally incident planewave with amplitude 1.

    +
  12. +
  13. Specify the operating frequency:

    +
    S:SetFrequency(0.4)
    +
    +
  14. +
  15. Obtain desired output:

    +
    transmission = S:GetPowerFlux('bottom')
    +print(transmission)
    +
    +

    This obtains the forward power flux in the bottom layer, which is also the transmitted power.

    +
  16. +
+
+
+

Fourier Modal Method formulations

+

There has been extensive literature on the best way to generate the Fourier series coefficients for the in-plane dielectric profiles of each layer. S4 implements a number of different formulations. The following functions determine which formulation is selected:

+
    +
  • UseDiscretizedEpsilon
  • +
  • UsePolarizationDecomposition
  • +
  • UseSubpixelSmoothing
  • +
  • UseJonesVectorBasis
  • +
  • UseNormalVectorBasis
  • +
+

In addition, the following functions control accuracy and the lattice truncation:

+
    +
  • SetResolution
  • +
  • SetLatticeTruncation
  • +
+

To simplify the choice for users, the table below summarizes the recommended settings. It is recommended to always use circular truncation unless there is a good reason to do otherwise. Speed indicates the speed of the Fourier coefficient generation, which is usually not the dominant part of the simulation time.

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionsCan handle Anisotropic?Recommended resolutionSpeedAccuracy
noneyesN/Afastpoor
Discyes8mediumpoor
Subpixelyes4mediummedium
Polno8slowgood
Pol+Normalno8slowgood
Pol+Jonesno8slowgood
Disc+Polno [1]4slowmedium
Disc+Pol+Normalno [1]4slowmedium
Disc+Pol+Jonesno [1]4slowmedium
+

Footnotes

+ + + + + +
[1](1, 2, 3) The formulation does not strictly work correctly for anisotropic media however it may still work. Proper support for anisotropic materials is in principle possible. There are currently no plans for implementing generation of the proper basis fields for this feature.
+
+
+

Examples

+

The source distribution of S4 includes numerous fully working didactic examples as well as examples replicating published results. +You can find these examples in the examples/ directory of the source distribution.

+
+
+ + +
+
+
+
+
+ +

Table Of Contents

+ + +

Previous topic

+

Download & Installation

+

Next topic

+

Lua API reference

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/build/html/units.html b/doc/build/html/units.html new file mode 100644 index 0000000..1809d80 --- /dev/null +++ b/doc/build/html/units.html @@ -0,0 +1,164 @@ + + + + + + + + Units & Coordinates — S4 1.1 documentation + + + + + + + + + + + + + + + +
+
+
+
+ +
+

Units & Coordinates

+

S4 solves the linear Maxwell’s equations, which are scale-invariant. +Therefore, S4 uses normalized units, so the conversion between the numbers in S4 and physically relevant numbers can sometimes be confusing. +Here we show how to perform these conversions and provide some examples.

+
+

Length, time, and frequency

+

The speed of light and the vacuum permittivity and vacuum permeability are all normalized to unity in S4. +Because of this, time is measured in units of length and frequency is measured in units of inverse length. +Due to the scale invariant nature of the linear Maxwell’s equations, there is no intrinsic length unit. +Instead, one can imagine that all lengths specified in S4 are multiples of a common reference length unit.

+

When the lattice vectors are set, this determines a length scale. +Suppose we have a square lattice with a periodicity of 680nm. It might be logical then to choose 1 micron as the base length unit, and to specify all lengths in microns. The lattice would then be set to the vectors (0.68, 0) and (0, 0.68). +Since frequency is in units of inverse length, then SetFrequency(1) corresponds to a wavelength of 680nm or a physical frequency of (c/680nm) = 441 THz, and SetFrequency(1.1) corresponds to a wavelength of (680/1.1) = 618nm, etc.

+
+
+

Amplitudes and powers

+

Typically S4 is used to compute transmission or reflection spectra, so the absolute units of incident power or amplitude are irrelevant. However, sometimes, it is necessary to be able to translate these figures into physical units.

+

Under a normally-incident planewave excitation, the incident power is 1 if the amplitude is 1, regardless of unit cell size. +At off-normal incidence, the incident power is reduced by a factor of cos(phi), where phi is the polar angle (angle from normal incidence).

+

The specified amplitudes are for the electric field. +If the incident power is considered to have units of Watts per unit-cell-area, then the electric field has units of Volts per square-root-of-unit-cell-area.

+
+
+ + +
+
+
+
+
+ +

Table Of Contents

+ + +

Previous topic

+

Python API reference

+

Next topic

+

Frequently Asked Questions

+

This Page

+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/source/install.rst b/doc/source/install.rst index 0275502..6a512d2 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -7,15 +7,21 @@ The latter is the preferred method for obtaining the latest features and bug fix Binary packages --------------- -The binary packages do not contain the examples and documentation. +The binary packages do not contain the examples and documentation, and are compiled with the bare minimum of features. You need to download that separately. * Version 1.1 - * Windows EXE (Lua frontend) - * Mac OS X 10.9 (Lua frontend) - * Examples and documentation + * `Windows (32-bit) EXE `_ (Lua frontend) + * `Mac OS X (compiled on 10.8.5) `_ (Lua frontend) + * `Examples and documentation `_ +* Version 1.0 (not recommended) + + * `Source with documentation and examples `_ + * `Windows EXE `_ + * `Mac OS X 10.6.8 `_ + GitHub repository -----------------