tessa-0.3.1/ 0002777 0001750 0001750 00000000000 10073013515 007634 5 0000000 0000000 tessa-0.3.1/doc/ 0002777 0001750 0001750 00000000000 10073013516 010402 5 0000000 0000000 tessa-0.3.1/doc/Makefile.am 0000644 0001750 0001750 00000000400 10003737755 012355 0000000 0000000 sgml_input = quickref.sgml
html_files = $(sgml_input:.sgml=.html)
if HAS_DB2HTML
htmldir = $(datadir)/doc/@PACKAGE@
html_DATA = $(html_files)
endif
EXTRA_DIST = $(sgml_input)
CLEANFILES = $(html_files)
%.html: %.sgml version
rm -f $@
$(DB2HTML) -u $<
tessa-0.3.1/doc/Makefile.in 0000644 0001750 0001750 00000020105 10073013342 012354 0000000 0000000 # Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DB2HTML = @DB2HTML@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
HAS_DB2HTML_FALSE = @HAS_DB2HTML_FALSE@
HAS_DB2HTML_TRUE = @HAS_DB2HTML_TRUE@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MPICC = @MPICC@
MPILIBS = @MPILIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
sgml_input = quickref.sgml
html_files = $(sgml_input:.sgml=.html)
@HAS_DB2HTML_TRUE@htmldir = $(datadir)/doc/@PACKAGE@
@HAS_DB2HTML_TRUE@html_DATA = $(html_files)
EXTRA_DIST = $(sgml_input)
CLEANFILES = $(html_files)
subdir = doc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/src/config.h
CONFIG_CLEAN_FILES = version
DIST_SOURCES =
DATA = $(html_DATA)
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am version.in
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu doc/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
version: $(top_builddir)/config.status version.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
uninstall-info-am:
htmlDATA_INSTALL = $(INSTALL_DATA)
install-htmlDATA: $(html_DATA)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(htmldir)
@list='$(html_DATA)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(htmlDATA_INSTALL) $$d$$p $(DESTDIR)$(htmldir)/$$f"; \
$(htmlDATA_INSTALL) $$d$$p $(DESTDIR)$(htmldir)/$$f; \
done
uninstall-htmlDATA:
@$(NORMAL_UNINSTALL)
@list='$(html_DATA)'; for p in $$list; do \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " rm -f $(DESTDIR)$(htmldir)/$$f"; \
rm -f $(DESTDIR)$(htmldir)/$$f; \
done
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(DATA)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(htmldir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am: install-htmlDATA
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-htmlDATA uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic distclean \
distclean-generic distdir dvi dvi-am info info-am install \
install-am install-data install-data-am install-exec \
install-exec-am install-htmlDATA install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \
uninstall-am uninstall-htmlDATA uninstall-info-am
%.html: %.sgml version
rm -f $@
$(DB2HTML) -u $<
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
tessa-0.3.1/doc/quickref.sgml 0000644 0001750 0001750 00000037761 10073011521 013021 0000000 0000000
]>
Tessa quick reference guide
Josselin
Mouette
École centrale de Lyon
josselin.mouette@ec-lyon.fr
Tessa
&version;
version &version;, 07 July 2004
This guide describes how to get quickly started with Tessa and run your first FDTD simulations. It doesn't describe how Tessa works, neither is it a complete description of Tessa's features.
Installing Tessa
When Tessa is not available as a binary package for your system, installation is done through GNU autotools:
./configure
make
(as root) make install
You will need as prerequisites:
The Hierarchical Data Format 5 library which is used to read and store all the data used by Tessa.
Zlib, which is a prerequisite for HDF5 anyway.
Necessary only if you use the provided module to generate the optical structures:
Python, the scripting language used to generate the structures.
NumPy, the Numeric Python extension. Numarray is not yet supported because it is too slow.
PyTables, which brings in HDF5 support for Python.
(optional) h5utils, a set of tools to manipulate HDF5 files, for e.g. cartography extraction.
(optional) The Fastest Fourier Transform of the West library, version 3, which allows to output frequency spectrums.
Creating your optical structure
The first step before running the simulation is to "draw" the structure you want to simulate. You can generate it as you like, as long as it is in the HF5 format. If you already have tools that generate e.g. three-dimensional data files in text format, you can convert them to HDF5 using h5fromtxt from the h5utils package.
If you start from scratch, you can use the python module provided with Tessa to generate a wide range of structures. First, create a file named e.g. tchat.py (the .py extension is for python scripts). This file should look like follows.
First, import the Tessa module.
from tessa import *
Then, create an IndexFile instance, name it as you want.
asv=IndexFile(5,4,2.4,index=1.444)
The 3 first arguments are the size of the structure. It is generally convenient to express them in micrometers or meters, but it is not necessary. The optional index parameter is the default index in the structure.
You can now fill your structure with geometric objects, e.g. cylinders.
asv.addobj(Cylinder(2.5,2,1,None,1,1.4,index=3.5))
asv.addobj(Cylinder(2.5,2,.7,None,1,1.4,index=1.444))
The two first required arguments for the Cylinder constructor tell the position of its center, the two following are the radii (the second radius being None, it is taken equal to the first), and the two final tell the vertical limitation for the cylinder. Order does matter: the second cylinder here will actually replace the first one where it is drawn. We obtain here a micro-ring.
asv.addobj(Block(1,1.3,-1,6,1,1.4,index=3.5))
asv.addobj(Block(3.7,4,-1,6,1,1.4,index=3.5))
These two blocks describe waveguides used to bring some optical signal to our micro-ring. The arguments are three couples of coordinates delimiting the block: x1, x2, y1, y2, z1, z2.
Note that you can also use absorbing materials. Just add a absor = value parameter, with value being the absorption coefficient in m-1.
Finally, we write the structure to HDF5 files.
asv.write("tchat1",delta_x=.05)
asv.write("tchat2",delta_x=.1,oversampling=1)
Two files are written here: tchat1.h5 and tchat2.h5. You can write as many as you want, with a delta_x parameter defining the space step for the FDTD simulation. Be careful to use the same unit you used to define the size of the structure. Here, the second file is written using an oversampling of 1 instead of the default (which is 4). This is useful if you want to see the result immediately (the script will run 64 times faster), but the HDF5 file won't be accurate enough for launchinga simulation. Use it when designing the structures.
You can draw several other types of geometric objects with this module. The complete documentation is accessible through python's internal help. Just run python in a shell, and, in the interpreter, type "import tessa; help(tessa)" (without the quotes). You can also easily make complex structures, such as photonic crystals, using loops just like in any other python script. If you don't know how to program in python, learn it. Even if you don't know how to program at all, achieving such things is easy.
Once you have your script, process it:
python tchat.py
It can take several minutes, but you only have to run it once. This will generate the HDF5 file(s). You can control the result using h5ls, h5totxt and h5topng.
Describing the simulation
Once you have a HDF5 file containing the structure you want to simulate, you have to fill the simulation file. So, create e.g. tchat.fdtd. The .fdtd extension is purely for convenience, but it is generally a good idea. This file is a simple list of variable = value lines.
Required parameters
index_file = tchat.h5
Defines the HDF5 file containing the simulated structure. Incidentally defines the size of the simulation.
delta_x = 0.1e-6
The spatial step of the simulation, in meters. Always use meters here, whatever unit you used when making the HDF5 file.
it_max = 100000
The total number of iterations.
One of the following:
freq = 2e14
The frequency around which the simulation is achieved, in Hz.
lambda = 1.5e-6
Ditto, but using the correspounding wavelength in meters.
Optional parameters
delta_t = 1.11e-16
The time step of an iteration. Defaults to a value slightly shorter than the maximum acceptable value for a stable simulation.
block_size = 10
The size of the basic calculation block, in cells (that means, in units of delta_x. It affects performance when too small or too large. Defaults to 10.
num_pml = 10
The size of the perfectly matched layers, in cells. Defaults to 10. Note that the PMLs are added outside the working space, so this parameter doesn't change the size of the actually computed structure.
pml_refl = 1.e-3
The theoretical reflection of the perfectly matched layers under normal incidence. Defaults to 1.e-3, that is 0.1 %.
One of the following:
injection = sinus 10
Set the injection to a single frequency. The parameter gives the number of periods during which the signal takes place.
injection = gauss 20
Set the injection to a gaussian spectrum around the base frequency. The parameter gives the relative frequency width in percent.
injection_file = kikoo.dat
Use the contents of a file as the amplitude of the injected signal. The file should be ASCII data, with one value per line, meaning one value per iteration.
The default injection is a sinus with 10 periods of starting time.
injection_pos = 10,50,25
The position of the injection, in cells. Defaults to the center of the simulation area. Currently, only dipole injection is supported.
injection_dir = 0.707,-0.707,0
The direction and maximal amplitude of the injection, in C.m.
The computed injection is multiplied by each of these factors
for the directions x, y and z respectively. Defaults to 0,0,1.
As a consequence, by default, the computed numerical values
are normalized for a dipole moment equal to 1 C.m.
Defining the output
Each of these parameters can be used as many times as you want, to have multiple outputs.
output_cartoE = 0-2000/100
Output cartographies for the electric field (all three components), in the HDF5 format. The parameter explains at which iterations the output should be made. The above example makes this output every 100 iterations during the first 2000 iterations. Any of these parameters can be omitted, defaulting respectively to zero, the last iteration and 100.
output_cartoH = /1000
Same as above, but for the magnetic field.
output_ponctE = 60,70,25
Output the three components of the electric field at each iteration, at the point defined by the three coordinates, in unit cells. The output file has 4 columns: the time in seconds, and the field in the 3 directions. If Tessa was built with support for discrete Fourier transforms, a file containing the Fourier transform is output as well, the first column containing the frequency in hertz.
output_ponctH = 60,70,25
Same as above, but for the magnetic field.
output_poynting = 45-55,70,45-55
Output the flow of the Poynting vector through a rectangular surface. The size of the surface is defined by two couples of coordinates and its position is defined by one single coordinate, in unit cells. The coordinates are always in the x, y, z order; the one being alone defines the direction of the plane.
total_loss = 1
Output the flow of the Poynting vector through all external surfaces. This is the total power lost by the system. Defaults to 0 (disabled).
Invoking Tessa
Run the simulation you defined above by typing tessa tchat.fdtd and wait. Tessa is believed to run faster than commercial implementation of the FDTD algorithm, but this algorithm is nevertheless slow.
Extracting the results
Viewing cartographies
The HDF5 format used for the output contains three-dimensional data. It is possible to directly view this data using tools like Vis5d+ or MayaVi, but it is generally more convenient to extract it as two-dimensional pictures. You can do it very easily using h5topng from the h5utils package. For example, to extract the data for the y component of the electric field at z = 25 (in unit cells), just run:
h5topng -Z -c bluered -S 3 -C tchat1.h5 -d y_comp -z 25 E*.h5
You can refer to the h5topng manual for more information.
Viewing spectra
The .dat files where spectra are written can be directly used for visualization. Just import them in a spreadsheet, or use xmgrace.
tessa-0.3.1/doc/version.in 0000644 0001750 0001750 00000000012 10003714421 012316 0000000 0000000 @VERSION@
tessa-0.3.1/src/ 0002777 0001750 0001750 00000000000 10073013515 010423 5 0000000 0000000 tessa-0.3.1/src/simul.c 0000644 0001750 0001750 00000115502 10063341120 011631 0000000 0000000 /* Copyright (c) 2003-2004 Ecole centrale de Lyon
*
* This program 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, version 2.
*
* 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "fdtd3d.h"
#include "utils.h"
#include "output.h"
#include "block.h"
#include
#include
#include
#include
#ifdef HAVE_MPI
#include
#endif
// Note: we use HH=H/cdtdx instead of H, winning a multiplication per point
#define pos_xp (pos+b->ny*b->nz)
#define pos_yp (pos+b->nz)
#define pos_zp (pos+1)
#define pos_xpn (iy*bxp->nz+iz)
#define pos_ypn (ix*byp->ny*byp->nz+iz)
#define pos_zpn ((ix*bzp->ny+iy)*bzp->nz)
#define pos_xm (pos-b->ny*b->nz)
#define pos_ym (pos-b->nz)
#define pos_zm (pos-1)
#define pos_xmn (((bxm->nx-1)*bxm->ny+iy)*bxm->nz+iz)
#define pos_ymn (((ix+1)*bym->ny-1)*bym->nz+iz)
#define pos_zmn ((ix*bzm->ny+iy+1)*bzm->nz-1)
// Warning: rotE is in fact -rot(E)
#define browse_block_with_rotE(INSTRUCTIONS) \
pos=0; \
for(ix=0;ixnx-1;ix++) \
{ \
for(iy=0;iyny-1;iy++) \
{ \
for(iz=0;iznz-1;iz++) \
{ \
rotEx=Ey[pos_zp]-Ey[pos]+Ez[pos]-Ez[pos_yp]; \
rotEy=Ez[pos_xp]-Ez[pos]+Ex[pos]-Ex[pos_zp]; \
rotEz=Ex[pos_yp]-Ex[pos]+Ey[pos]-Ey[pos_xp]; \
INSTRUCTIONS \
pos++; \
} \
rotEx=bzp->Ey[pos_zpn]-Ey[pos]+Ez[pos]- Ez[pos_yp] ; \
rotEy= Ez[pos_xp] -Ez[pos]+Ex[pos]-bzp->Ex[pos_zpn]; \
rotEz= Ex[pos_yp] -Ex[pos]+Ey[pos]- Ey[pos_xp] ; \
INSTRUCTIONS \
pos++; \
} \
for(iz=0;iznz-1;iz++) \
{ \
rotEx= Ey[pos_zp] -Ey[pos]+Ez[pos]-byp->Ez[pos_ypn]; \
rotEy= Ez[pos_xp] -Ez[pos]+Ex[pos]- Ex[pos_zp] ; \
rotEz=byp->Ex[pos_ypn]-Ex[pos]+Ey[pos]- Ey[pos_xp] ; \
INSTRUCTIONS \
pos++; \
} \
rotEx=bzp->Ey[pos_zpn]-Ey[pos]+Ez[pos]-byp->Ez[pos_ypn]; \
rotEy= Ez[pos_xp] -Ez[pos]+Ex[pos]-bzp->Ex[pos_zpn]; \
rotEz=byp->Ex[pos_ypn]-Ex[pos]+Ey[pos]- Ey[pos_xp] ; \
INSTRUCTIONS \
pos++; \
} \
for(iy=0;iyny-1;iy++) \
{ \
for(iz=0;iznz-1;iz++) \
{ \
rotEx= Ey[pos_zp] -Ey[pos]+Ez[pos]- Ez[pos_yp] ; \
rotEy=bxp->Ez[pos_xpn]-Ez[pos]+Ex[pos]- Ex[pos_zp] ; \
rotEz= Ex[pos_yp] -Ex[pos]+Ey[pos]-bxp->Ey[pos_xpn]; \
INSTRUCTIONS \
pos++; \
} \
rotEx=bzp->Ey[pos_zpn]-Ey[pos]+Ez[pos]- Ez[pos_yp] ; \
rotEy=bxp->Ez[pos_xpn]-Ez[pos]+Ex[pos]-bzp->Ex[pos_zpn]; \
rotEz= Ex[pos_yp] -Ex[pos]+Ey[pos]-bxp->Ey[pos_xpn]; \
INSTRUCTIONS \
pos++; \
} \
for(iz=0;iznz-1;iz++) \
{ \
rotEx= Ey[pos_zp] -Ey[pos]+Ez[pos]-byp->Ez[pos_ypn]; \
rotEy=bxp->Ez[pos_xpn]-Ez[pos]+Ex[pos]- Ex[pos_zp] ; \
rotEz=byp->Ex[pos_ypn]-Ex[pos]+Ey[pos]-bxp->Ey[pos_xpn]; \
INSTRUCTIONS \
pos++; \
} \
rotEx=bzp->Ey[pos_zpn]-Ey[pos]+Ez[pos]-byp->Ez[pos_ypn]; \
rotEy=bxp->Ez[pos_xpn]-Ez[pos]+Ex[pos]-bzp->Ex[pos_zpn]; \
rotEz=byp->Ex[pos_ypn]-Ex[pos]+Ey[pos]-bxp->Ey[pos_xpn]; \
INSTRUCTIONS \
pos++; \
assert(pos==b->nx*b->ny*b->nz)
#define browse_block_with_rotH(INSTRUCTIONS) \
pos=0; \
ix=0;iy=0;iz=0; \
rotHx=HHz[pos]-bym->HHz[pos_ymn]+bzm->HHy[pos_zmn]-HHy[pos]; \
rotHy=HHx[pos]-bzm->HHx[pos_zmn]+bxm->HHz[pos_xmn]-HHz[pos]; \
rotHz=HHy[pos]-bxm->HHy[pos_xmn]+bym->HHx[pos_ymn]-HHx[pos]; \
INSTRUCTIONS \
pos++; \
for(iz=1;iznz;iz++) \
{ \
rotHx=HHz[pos]-bym->HHz[pos_ymn]+ HHy[pos_zm] -HHy[pos]; \
rotHy=HHx[pos]- HHx[pos_zm] +bxm->HHz[pos_xmn]-HHz[pos]; \
rotHz=HHy[pos]-bxm->HHy[pos_xmn]+bym->HHx[pos_ymn]-HHx[pos]; \
INSTRUCTIONS \
pos++; \
} \
for(iy=1;iyny;iy++) \
{ \
iz=0; \
rotHx=HHz[pos]- HHz[pos_ym] +bzm->HHy[pos_zmn]-HHy[pos]; \
rotHy=HHx[pos]-bzm->HHx[pos_zmn]+bxm->HHz[pos_xmn]-HHz[pos]; \
rotHz=HHy[pos]-bxm->HHy[pos_xmn]+ HHx[pos_ym] -HHx[pos]; \
INSTRUCTIONS \
pos++; \
for(iz=1;iznz;iz++) \
{ \
rotHx=HHz[pos]- HHz[pos_ym] + HHy[pos_zm] -HHy[pos]; \
rotHy=HHx[pos]- HHx[pos_zm] +bxm->HHz[pos_xmn]-HHz[pos]; \
rotHz=HHy[pos]-bxm->HHy[pos_xmn]+ HHx[pos_ym] -HHx[pos]; \
INSTRUCTIONS \
pos++; \
} \
} \
for(ix=1;ixnx;ix++) \
{ \
iy=0;iz=0; \
rotHx=HHz[pos]-bym->HHz[pos_ymn]+bzm->HHy[pos_zmn]-HHy[pos]; \
rotHy=HHx[pos]-bzm->HHx[pos_zmn]+ HHz[pos_xm] -HHz[pos]; \
rotHz=HHy[pos]- HHy[pos_xm] +bym->HHx[pos_ymn]-HHx[pos]; \
INSTRUCTIONS \
pos++; \
for(iz=1;iznz;iz++) \
{ \
rotHx=HHz[pos]-bym->HHz[pos_ymn]+ HHy[pos_zm] -HHy[pos]; \
rotHy=HHx[pos]- HHx[pos_zm] + HHz[pos_xm] -HHz[pos]; \
rotHz=HHy[pos]- HHy[pos_xm] +bym->HHx[pos_ymn]-HHx[pos]; \
INSTRUCTIONS \
pos++; \
} \
for(iy=1;iyny;iy++) \
{ \
iz=0; \
rotHx=HHz[pos]- HHz[pos_ym] +bzm->HHy[pos_zmn]-HHy[pos]; \
rotHy=HHx[pos]-bzm->HHx[pos_zmn]+ HHz[pos_xm] -HHz[pos]; \
rotHz=HHy[pos]- HHy[pos_xm] + HHx[pos_ym] -HHx[pos]; \
INSTRUCTIONS \
pos++; \
for(iz=1;iznz;iz++) \
{ \
rotHx=HHz[pos]-HHz[pos_ym]+HHy[pos_zm]-HHy[pos]; \
rotHy=HHx[pos]-HHx[pos_zm]+HHz[pos_xm]-HHz[pos]; \
rotHz=HHy[pos]-HHy[pos_xm]+HHx[pos_ym]-HHx[pos]; \
INSTRUCTIONS \
pos++; \
} \
} \
} \
assert(pos==b->nx*b->ny*b->nz)
static void iter_H_plain_block(varBlock *b)
{
int pos;
// TODO: benchmark when we replace pos by a macro based on ix,iy,iz.
int ix,iy,iz;
varBlock *bxp=b->block_xp;
varBlock *byp=b->block_yp;
varBlock *bzp=b->block_zp;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double rotEx,rotEy,rotEz;
browse_block_with_rotE(
HHx[pos]+=rotEx;
HHy[pos]+=rotEy;
HHz[pos]+=rotEz;
);
}
static void iter_E_plain_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxm=b->block_xm;
varBlock *bym=b->block_ym;
varBlock *bzm=b->block_zm;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *cn=b->cn;
double rotHx,rotHy,rotHz;
browse_block_with_rotH(
Ex[pos]+=cn[pos]*rotHx;
Ey[pos]+=cn[pos]*rotHy;
Ez[pos]+=cn[pos]*rotHz;
);
}
static void iter_E_abs_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxm=b->block_xm;
varBlock *bym=b->block_ym;
varBlock *bzm=b->block_zm;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumEx=b->absor->sumEx;
double *sumEy=b->absor->sumEy;
double *sumEz=b->absor->sumEz;
double *cn=b->cn;
double *dec=b->absor->dec;
double rotHx,rotHy,rotHz;
browse_block_with_rotH(
Ex[pos]=( (1-dec[pos])*Ex[pos] + cn[pos]*rotHx
- SQUARE(dec[pos]*dec[pos])*sumEx[pos] )/(1+dec[pos]);
sumEx[pos]+=Ex[pos];
Ey[pos]=( (1-dec[pos])*Ey[pos] + cn[pos]*rotHy
- SQUARE(dec[pos]*dec[pos])*sumEy[pos] )/(1+dec[pos]);
sumEy[pos]+=Ey[pos];
Ez[pos]=( (1-dec[pos])*Ez[pos] + cn[pos]*rotHz
- SQUARE(dec[pos]*dec[pos])*sumEz[pos] )/(1+dec[pos]);
sumEz[pos]+=Ez[pos];
);
}
static void iter_H_PML_x_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxp=b->block_xp;
varBlock *byp=b->block_yp;
varBlock *bzp=b->block_zp;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumrotEx=b->PML->sumrotEx;
double decay=b->PML->x_decay;
double x_rotcoef=b->PML->x_rotcoef;
double x_sumrotcoef=b->PML->x_sumrotcoef;
double rotEx,rotEy,rotEz;
browse_block_with_rotE(
HHx[pos]+=x_rotcoef*rotEx+x_sumrotcoef*sumrotEx[pos];
sumrotEx[pos]+=rotEx;
HHy[pos]=HHy[pos]*decay+rotEy;
HHz[pos]=HHz[pos]*decay+rotEz;
);
}
static void iter_E_PML_x_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxm=b->block_xm;
varBlock *bym=b->block_ym;
varBlock *bzm=b->block_zm;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumrotHx=b->PML->sumrotHHx;
double *cn=b->cn;
double decay=b->PML->x_decay;
double x_rotcoef=b->PML->x_rotcoef;
double x_sumrotcoef=b->PML->x_sumrotcoef;
double rotHx,rotHy,rotHz;
browse_block_with_rotH(
Ex[pos]+=cn[pos]*(x_rotcoef*rotHx+x_sumrotcoef*sumrotHx[pos]);
sumrotHx[pos]+=rotHx;
Ey[pos]=Ey[pos]*decay+cn[pos]*rotHy;
Ez[pos]=Ez[pos]*decay+cn[pos]*rotHz;
);
}
static void iter_H_PML_y_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxp=b->block_xp;
varBlock *byp=b->block_yp;
varBlock *bzp=b->block_zp;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumrotEy=b->PML->sumrotEy;
double decay=b->PML->y_decay;
double y_rotcoef=b->PML->y_rotcoef;
double y_sumrotcoef=b->PML->y_sumrotcoef;
double rotEx,rotEy,rotEz;
browse_block_with_rotE(
HHx[pos]=HHx[pos]*decay+rotEx;
HHy[pos]+=y_rotcoef*rotEy+y_sumrotcoef*sumrotEy[pos];
sumrotEy[pos]+=rotEy;
HHz[pos]=HHz[pos]*decay+rotEz;
);
}
static void iter_E_PML_y_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxm=b->block_xm;
varBlock *bym=b->block_ym;
varBlock *bzm=b->block_zm;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumrotHy=b->PML->sumrotHHy;
double *cn=b->cn;
double decay=b->PML->y_decay;
double y_rotcoef=b->PML->y_rotcoef;
double y_sumrotcoef=b->PML->y_sumrotcoef;
double rotHx,rotHy,rotHz;
browse_block_with_rotH(
Ex[pos]=Ex[pos]*decay+cn[pos]*rotHx;
Ey[pos]+=cn[pos]*(y_rotcoef*rotHy+y_sumrotcoef*sumrotHy[pos]);
sumrotHy[pos]+=rotHy;
Ez[pos]=Ez[pos]*decay+cn[pos]*rotHz;
);
}
static void iter_H_PML_z_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxp=b->block_xp;
varBlock *byp=b->block_yp;
varBlock *bzp=b->block_zp;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumrotEz=b->PML->sumrotEz;
double decay=b->PML->z_decay;
double z_rotcoef=b->PML->z_rotcoef;
double z_sumrotcoef=b->PML->z_sumrotcoef;
double rotEx,rotEy,rotEz;
browse_block_with_rotE(
HHx[pos]=HHx[pos]*decay+rotEx;
HHy[pos]=HHy[pos]*decay+rotEy;
HHz[pos]+=z_rotcoef*rotEz+z_sumrotcoef*sumrotEz[pos];
sumrotEz[pos]+=rotEz;
);
}
static void iter_E_PML_z_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxm=b->block_xm;
varBlock *bym=b->block_ym;
varBlock *bzm=b->block_zm;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumrotHz=b->PML->sumrotHHz;
double *cn=b->cn;
double decay=b->PML->z_decay;
double z_rotcoef=b->PML->z_rotcoef;
double z_sumrotcoef=b->PML->z_sumrotcoef;
double rotHx,rotHy,rotHz;
browse_block_with_rotH(
Ex[pos]=Ex[pos]*decay+cn[pos]*rotHx;
Ey[pos]=Ey[pos]*decay+cn[pos]*rotHy;
Ez[pos]+=cn[pos]*(z_rotcoef*rotHz+z_sumrotcoef*sumrotHz[pos]);
sumrotHz[pos]+=rotHz;
);
}
static void iter_H_PML_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxp=b->block_xp;
varBlock *byp=b->block_yp;
varBlock *bzp=b->block_zp;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumrotEx=b->PML->sumrotEx;
double *sumrotEy=b->PML->sumrotEy;
double *sumrotEz=b->PML->sumrotEz;
double *sumHHx=b->PML->sumHHx;
double *sumHHy=b->PML->sumHHy;
double *sumHHz=b->PML->sumHHz;
double x_decay=b->PML->x_decay;
double y_decay=b->PML->y_decay;
double z_decay=b->PML->z_decay;
double x_rotcoef=b->PML->x_rotcoef;
double y_rotcoef=b->PML->y_rotcoef;
double z_rotcoef=b->PML->z_rotcoef;
double x_sumrotcoef=b->PML->x_sumrotcoef;
double y_sumrotcoef=b->PML->y_sumrotcoef;
double z_sumrotcoef=b->PML->z_sumrotcoef;
double x_sumcoef=b->PML->x_sumcoef;
double y_sumcoef=b->PML->y_sumcoef;
double z_sumcoef=b->PML->z_sumcoef;
double rotEx,rotEy,rotEz;
browse_block_with_rotE(
HHx[pos]=HHx[pos]*x_decay+x_rotcoef*rotEx+x_sumrotcoef*sumrotEx[pos]-x_sumcoef*sumHHx[pos];
sumHHx[pos]+=HHx[pos];
sumrotEx[pos]+=rotEx;
HHy[pos]=HHy[pos]*y_decay+y_rotcoef*rotEy+y_sumrotcoef*sumrotEy[pos]-y_sumcoef*sumHHy[pos];
sumHHy[pos]+=HHy[pos];
sumrotEy[pos]+=rotEy;
HHz[pos]=HHz[pos]*z_decay+z_rotcoef*rotEz+z_sumrotcoef*sumrotEz[pos]-z_sumcoef*sumHHz[pos];
sumHHz[pos]+=HHz[pos];
sumrotEz[pos]+=rotEz;
);
}
static void iter_E_PML_block(varBlock *b)
{
int pos;
int ix,iy,iz;
varBlock *bxm=b->block_xm;
varBlock *bym=b->block_ym;
varBlock *bzm=b->block_zm;
double *HHx=b->HHx;
double *HHy=b->HHy;
double *HHz=b->HHz;
double *Ex=b->Ex;
double *Ey=b->Ey;
double *Ez=b->Ez;
double *sumrotHx=b->PML->sumrotHHx;
double *sumrotHy=b->PML->sumrotHHy;
double *sumrotHz=b->PML->sumrotHHz;
double *sumEx=b->PML->sumEx;
double *sumEy=b->PML->sumEy;
double *sumEz=b->PML->sumEz;
double *cn=b->cn;
double x_decay=b->PML->x_decay;
double y_decay=b->PML->y_decay;
double z_decay=b->PML->z_decay;
double x_rotcoef=b->PML->x_rotcoef;
double y_rotcoef=b->PML->y_rotcoef;
double z_rotcoef=b->PML->z_rotcoef;
double x_sumrotcoef=b->PML->x_sumrotcoef;
double y_sumrotcoef=b->PML->y_sumrotcoef;
double z_sumrotcoef=b->PML->z_sumrotcoef;
double x_sumcoef=b->PML->x_sumcoef;
double y_sumcoef=b->PML->y_sumcoef;
double z_sumcoef=b->PML->z_sumcoef;
double rotHx,rotHy,rotHz;
browse_block_with_rotH(
Ex[pos]=Ex[pos]*x_decay+cn[pos]*(x_rotcoef*rotHx+x_sumrotcoef*sumrotHx[pos])-x_sumcoef*sumEx[pos];
sumEx[pos]+=Ex[pos];
sumrotHx[pos]+=rotHx;
Ey[pos]=Ey[pos]*y_decay+cn[pos]*(y_rotcoef*rotHy+y_sumrotcoef*sumrotHy[pos])-y_sumcoef*sumEy[pos];
sumEy[pos]+=Ey[pos];
sumrotHy[pos]+=rotHy;
Ez[pos]=Ez[pos]*z_decay+cn[pos]*(z_rotcoef*rotHz+z_sumrotcoef*sumrotHz[pos])-z_sumcoef*sumEz[pos];
sumEz[pos]+=Ez[pos];
sumrotHz[pos]+=rotHz;
);
}
#undef pos_xp
#undef pos_yp
#undef pos_zp
#undef pos_xpn
#undef pos_ypn
#undef pos_zpn
#undef pos_xm
#undef pos_ym
#undef pos_zm
#undef pos_xmn
#undef pos_ymn
#undef pos_zmn
#undef browse_block_with_rotE
#undef browse_block_with_rotH
static double integ_poynt_x(const varOutputPoynt *p,varBlock *start_block,varBlockList *b)
{
varBlock *cur_block;
double res=0;
int miny,minz,maxy,maxz;
int px = p->x1 - start_block->off_x;
int i,j,pos;
while(p->y2 > start_block->off_y)
{
cur_block=start_block;
miny=MAX(0,p->y1-cur_block->off_y);
maxy=MIN(cur_block->ny,p->y2-cur_block->off_y);
while(p->z2 > cur_block->off_z)
{
#ifdef HAVE_MPI
if(cur_block->mpi_node==b->mpi_node)
#endif
{
minz=MAX(0,p->z1-cur_block->off_z);
maxz=MIN(cur_block->nz,p->z2-cur_block->off_z);
for(i=miny;iny+i)*cur_block->nz+j);
res+=cur_block->Ey[pos]*cur_block->HHz[pos]-cur_block->HHy[pos]*cur_block->Ez[pos];
}
}
cur_block=cur_block->block_zp;
}
start_block=start_block->block_yp;
}
return res;
}
static double integ_poynt_y(const varOutputPoynt *p,varBlock *start_block,varBlockList *b)
{
varBlock *cur_block;
double res=0;
int minz,minx,maxz,maxx;
int py = p->y1 - start_block->off_y;
int i,j,pos;
while(p->z2 > start_block->off_z)
{
cur_block=start_block;
minz=MAX(0,p->z1-cur_block->off_z);
maxz=MIN(cur_block->nz,p->z2-cur_block->off_z);
while(p->x2 > cur_block->off_x)
{
#ifdef HAVE_MPI
if(cur_block->mpi_node==b->mpi_node)
#endif
{
minx=MAX(0,p->x1-cur_block->off_x);
maxx=MIN(cur_block->nx,p->x2-cur_block->off_x);
for(i=minz;iny+py)*cur_block->nz+i);
res+=cur_block->Ez[pos]*cur_block->HHx[pos]-cur_block->HHz[pos]*cur_block->Ex[pos];
}
}
cur_block=cur_block->block_xp;
}
start_block=start_block->block_zp;
}
return res;
}
static double integ_poynt_z(const varOutputPoynt *p,varBlock *start_block,varBlockList *b)
{
varBlock *cur_block;
double res=0;
int minx,miny,maxx,maxy;
int pz = p->z1 - start_block->off_z;
int i,j,pos;
while(p->x2 > start_block->off_x)
{
cur_block=start_block;
minx=MAX(0,p->x1-cur_block->off_x);
maxx=MIN(cur_block->nx,p->x2-cur_block->off_x);
while(p->y2 > cur_block->off_y)
{
#ifdef HAVE_MPI
if(cur_block->mpi_node==b->mpi_node)
#endif
{
miny=MAX(0,p->y1-cur_block->off_y);
maxy=MIN(cur_block->ny,p->y2-cur_block->off_y);
for(i=minx;iny+j)*cur_block->nz+pz);
res+=cur_block->Ex[pos]*cur_block->HHy[pos]-cur_block->HHx[pos]*cur_block->Ey[pos];
}
}
cur_block=cur_block->block_yp;
}
start_block=start_block->block_xp;
}
return res;
}
#ifdef HAVE_MPI
static int field_buflen;
static int cur_send_request;
static double **before_buffer;
static double **after_buffer;
static MPI_Request *before_reqs;
static MPI_Request *after_reqs;
static inline void field_x_pack(double *dest, varBlock *block, double *field)
{
memcpy(dest,field,block->ny*block->nz*sizeof(double));
}
static inline void field_x_unpack(double *src, varBlock *block, double *field)
{
memcpy(field,src,block->ny*block->nz*sizeof(double));
}
static inline void field_y_pack(double *dest, varBlock *block, double *field)
{
int i;
for(i=0;inx;i++)
memcpy(dest+i*block->nz,field+i*block->ny*block->nz,block->nz*sizeof(double));
}
static inline void field_y_unpack(double *src, varBlock *block, double *field)
{
int i;
for(i=0;inx;i++)
memcpy(field+i*block->ny*block->nz,src+i*block->nz,block->nz*sizeof(double));
}
static inline void field_z_pack(double *dest, varBlock *block, double *field)
{
int i,j;
for(i=0;inx;i++)
for(j=0;jny;j++)
dest[i*block->ny+j]=field[(i*block->ny+j)*block->nz];
}
static inline void field_z_unpack(double *src, varBlock *block, double *field)
{
int i,j;
for(i=0;inx;i++)
for(j=0;jny;j++)
field[(i*block->ny+j)*block->nz]=src[i*block->ny+j];
}
static void initiate_receive(int num, double **buf, MPI_Request *reqs, int tag)
{
int i;
for(i=0;impi_blocks_before, before_reqs, MPI_STATUSES_IGNORE);
for(i=0;impi_blocks_before;i++)
{
p=(int *) before_buffer[i];
bl=b->blocks+p[0];
switch(p[1])
{
case DIR_X:
field_x_unpack(before_buffer[i]+1, bl, bl->HHy+(bl->nx-1)*bl->ny*bl->nz);
field_x_unpack(before_buffer[i]+1+bl->ny*bl->nz, bl, bl->HHz+(bl->nx-1)*bl->ny*bl->nz);
break;
case DIR_Y:
field_y_unpack(before_buffer[i]+1, bl, bl->HHz+(bl->ny-1)*bl->nz);
field_y_unpack(before_buffer[i]+1+bl->nz*bl->nx, bl, bl->HHx+(bl->ny-1)*bl->nz);
break;
case DIR_Z:
field_z_unpack(before_buffer[i]+1, bl, bl->HHx+bl->nz-1);
field_z_unpack(before_buffer[i]+1+bl->nx*bl->ny, bl, bl->HHy+bl->nz-1);
break;
default:
panic("Cannot find field direction in MPI message.");
}
}
}
static void block_propagate_H(varBlock *bl, varBlock *first_block)
{
int i;
int num=bl-first_block;
int *p;
if(bl->block_xp->mpi_node != bl->mpi_node)
{
i=cur_send_request++;
p=(int *) after_buffer[i]; // Gruik gruik
// The first 8 bytes are used to store
// block number and direction
p[0]=num;
p[1]=DIR_X;
field_x_pack(after_buffer[i]+1, bl, bl->HHy+(bl->nx-1)*bl->ny*bl->nz);
field_x_pack(after_buffer[i]+1+bl->ny*bl->nz, bl, bl->HHz+(bl->nx-1)*bl->ny*bl->nz);
// printf("Node %i sending block %ix to node %i.\n",bl->mpi_node,num,bl->block_xp->mpi_node);
MPI_Isend(after_buffer[i], 1+2*bl->ny*bl->nz, MPI_DOUBLE, bl->block_xp->mpi_node, TAG_HFIELD, MPI_COMM_WORLD, after_reqs+i);
}
if(bl->block_yp->mpi_node != bl->mpi_node)
{
i=cur_send_request++;
p=(int *) after_buffer[i];
p[0]=num;
p[1]=DIR_Y;
field_y_pack(after_buffer[i]+1, bl, bl->HHz+(bl->ny-1)*bl->nz);
field_y_pack(after_buffer[i]+1+bl->nz*bl->nx, bl, bl->HHx+(bl->ny-1)*bl->nz);
// printf("Node %i sending block %iy to node %i.\n",bl->mpi_node,num,bl->block_yp->mpi_node);
MPI_Isend(after_buffer[i], 1+2*bl->nz*bl->nx, MPI_DOUBLE, bl->block_yp->mpi_node, TAG_HFIELD, MPI_COMM_WORLD, after_reqs+i);
}
if(bl->block_zp->mpi_node != bl->mpi_node)
{
i=cur_send_request++;
p=(int *) after_buffer[i];
p[0]=num;
p[1]=DIR_Z;
field_z_pack(after_buffer[i]+1, bl, bl->HHx+bl->nz-1);
field_z_pack(after_buffer[i]+1+bl->nx*bl->ny, bl, bl->HHy+bl->nz-1);
// printf("Node %i sending block %iz to node %i.\n",bl->mpi_node,num,bl->block_zp->mpi_node);
MPI_Isend(after_buffer[i], 1+2*bl->nx*bl->ny, MPI_DOUBLE, bl->block_zp->mpi_node, TAG_HFIELD, MPI_COMM_WORLD, after_reqs+i);
}
}
static void receive_E_msgs(varBlockList *b)
{
varBlock *bl;
int i;
int *p;
// MPI_Waitall(b->mpi_blocks_after, after_reqs, MPI_STATUSES_IGNORE);
for(i=0;impi_blocks_after;i++)
{
p=(int *) after_buffer[i];
bl=b->blocks+p[0];
switch(p[1])
{
case DIR_X:
field_x_unpack(after_buffer[i]+1, bl, bl->Ey);
field_x_unpack(after_buffer[i]+1+bl->ny*bl->nz, bl, bl->Ez);
break;
case DIR_Y:
field_y_unpack(after_buffer[i]+1, bl, bl->Ez);
field_y_unpack(after_buffer[i]+1+bl->nz*bl->nx, bl, bl->Ex);
break;
case DIR_Z:
field_z_unpack(after_buffer[i]+1, bl, bl->Ex);
field_z_unpack(after_buffer[i]+1+bl->nx*bl->ny, bl, bl->Ey);
break;
default:
panic("Cannot find field direction in MPI message.");
}
}
}
static void block_propagate_E(varBlock *bl, varBlock *first_block)
{
int i;
int num=bl-first_block;
int *p;
if(bl->block_xm->mpi_node != bl->mpi_node)
{
i=cur_send_request++;
p=(int *) before_buffer[i];
p[0]=num;
p[1]=DIR_X;
field_x_pack(before_buffer[i]+1, bl, bl->Ey);
field_x_pack(before_buffer[i]+1+bl->ny*bl->nz, bl, bl->Ez);
MPI_Isend(before_buffer[i], 1+2*bl->ny*bl->nz, MPI_DOUBLE, bl->block_xm->mpi_node, TAG_EFIELD, MPI_COMM_WORLD, before_reqs+i);
}
if(bl->block_ym->mpi_node != bl->mpi_node)
{
i=cur_send_request++;
p=(int *) before_buffer[i];
p[0]=num;
p[1]=DIR_Y;
field_y_pack(before_buffer[i]+1, bl, bl->Ez);
field_y_pack(before_buffer[i]+1+bl->nz*bl->nx, bl, bl->Ex);
MPI_Isend(before_buffer[i], 1+2*bl->nz*bl->nx, MPI_DOUBLE, bl->block_ym->mpi_node, TAG_EFIELD, MPI_COMM_WORLD, before_reqs+i);
}
if(bl->block_zm->mpi_node != bl->mpi_node)
{
i=cur_send_request++;
p=(int *) before_buffer[i];
p[0]=num;
p[1]=DIR_Z;
field_z_pack(before_buffer[i]+1, bl, bl->Ex);
field_z_pack(before_buffer[i]+1+bl->nx*bl->ny, bl, bl->Ey);
MPI_Isend(before_buffer[i], 1+2*bl->nx*bl->ny, MPI_DOUBLE, bl->block_zm->mpi_node, TAG_EFIELD, MPI_COMM_WORLD, before_reqs+i);
}
}
#endif // HAVE_MPI
int RunSimul(SimulDesc *thesimul)
{
int max_iteration=thesimul->simul->it_max;
int iteration,i;
float time_begin,time_end;
varBlockList *b=index_array_to_blocks_with_pml(thesimul);
varBlock *curBlock;
double cdtdx=CELERITY*thesimul->simul->delta_t/thesimul->space->delta_x;
int total_cells=thesimul->space->nx*thesimul->space->ny*thesimul->space->nz;
varBlock *inj_block=search_block(b,thesimul->inj->x,thesimul->inj->y,thesimul->inj->z);
int inj_pos_in_block=offset_in_block(inj_block,thesimul->inj->x,thesimul->inj->y,thesimul->inj->z);
double *output_buffer=NULL;
double *field_buf=NULL; // A temporary buffer to store the
// field in a block. Only for MPI.
int nb_ponctoutput=thesimul->output->nb_poncts;
varBlock **ponct_out_blocks=myalloc(nb_ponctoutput*sizeof(varBlock *));
int *ponct_out_offsets=myalloc(nb_ponctoutput*sizeof(int));
varOutputPonct *tmp_ponct;
int nb_poyntoutput=thesimul->output->nb_poynts;
varBlock **poynt_out_init_blocks=myalloc(nb_poyntoutput*sizeof(varBlock *));
varOutputPoynt *tmp_poynt;
#ifdef HAVE_MPI
double **mpi_buffers;
MPI_Request *mpi_reqs;
// The maximum send buffer we'll need consists in 2 fields for
// each allocated block.
field_buflen=2*SQUARE(MAX(thesimul->space->num_pml,thesimul->space->block_size))+1;
// We allocate 8 extra bytes at the beginning for the 2 ints
// (block number and direction)
mpi_buffers=myalloc((b->mpi_blocks_before+b->mpi_blocks_after)*sizeof(double *));
before_buffer=mpi_buffers;
after_buffer=mpi_buffers+b->mpi_blocks_before;
mpi_reqs=myalloc((b->mpi_blocks_before+b->mpi_blocks_after)*sizeof(MPI_Request));
before_reqs=mpi_reqs;
after_reqs=mpi_reqs+b->mpi_blocks_before;
for(i=0;impi_blocks_before;i++)
before_buffer[i]=myalloc(field_buflen*sizeof(double));
for(i=0;impi_blocks_after;i++)
after_buffer[i]=myalloc(field_buflen*sizeof(double));
#endif // HAVE_MPI
// Only allocate output buffer on first node.
if(thesimul->output->nb_cartos)
{
#ifdef HAVE_MPI
if(b->mpi_node==0)
{
field_buf=myalloc(CUBE(MAX(thesimul->space->num_pml,thesimul->space->block_size))*sizeof(double));
output_buffer=myalloc(total_cells*sizeof(double));
}
#else // HAVE_MPI
output_buffer=myalloc(total_cells*sizeof(double));
#endif // HAVE_MPI
}
for(i=0;ioutput->poncts[i]);
ponct_out_blocks[i]=search_block(b,tmp_ponct->x,tmp_ponct->y,tmp_ponct->z);
ponct_out_offsets[i]=offset_in_block(ponct_out_blocks[i],tmp_ponct->x,tmp_ponct->y,tmp_ponct->z);
}
for(i=0;ioutput->poynts[i]);
poynt_out_init_blocks[i] = search_block(b,tmp_poynt->x1,tmp_poynt->y1,tmp_poynt->z1);
}
time_begin=get_time();
for(iteration=0;iterationmpi_node == 0 &&
#endif
iteration%10 == 0 )
{
printf("\rIteration #%i --- %i %% completed",iteration,iteration*100/max_iteration);
fflush(stdout);
}
// Dipole injection
#ifdef HAVE_MPI
if(b->mpi_node == inj_block->mpi_node)
#endif
{
inj_block->Ex[inj_pos_in_block] += thesimul->inj->dir_x*thesimul->inj->injection[iteration];
inj_block->Ey[inj_pos_in_block] += thesimul->inj->dir_y*thesimul->inj->injection[iteration];
inj_block->Ez[inj_pos_in_block] += thesimul->inj->dir_z*thesimul->inj->injection[iteration];
}
// iterate H
#ifdef HAVE_MPI
cur_send_request=0;
initiate_receive(b->mpi_blocks_before, before_buffer, before_reqs, TAG_HFIELD);
// Go in the reverse order so that the field to be sent
// is computed first
for(i=b->mpi_endblock;i-->b->mpi_startblock;)
#else
for(i=0;in;i++)
#endif
{
curBlock=b->blocks+i;
if(curBlock->PML==NULL)
iter_H_plain_block(curBlock);
else
{
switch(curBlock->PML->block_type)
{
case BLOCK_PML_FACE_X:
iter_H_PML_x_block(curBlock);
break;
case BLOCK_PML_FACE_Y:
iter_H_PML_y_block(curBlock);
break;
case BLOCK_PML_FACE_Z:
iter_H_PML_z_block(curBlock);
break;
default:
iter_H_PML_block(curBlock);
}
}
#ifdef HAVE_MPI
block_propagate_H(curBlock,b->blocks);
#endif
}
#ifdef HAVE_MPI
MPI_Waitall(b->mpi_blocks_after+b->mpi_blocks_before, mpi_reqs, MPI_STATUSES_IGNORE);
receive_H_msgs(b);
// MPI_Barrier(MPI_COMM_WORLD);
#endif
// iterate E
#ifdef HAVE_MPI
cur_send_request=0;
initiate_receive(b->mpi_blocks_after, after_buffer, after_reqs, TAG_EFIELD);
for(i=b->mpi_startblock;impi_endblock;i++)
#else
for(i=0;in;i++)
#endif
{
curBlock=b->blocks+i;
if(curBlock->PML==NULL)
{
if(curBlock->absor==NULL)
iter_E_plain_block(curBlock);
else
iter_E_abs_block(curBlock);
}
else
{
switch(curBlock->PML->block_type)
{
case BLOCK_PML_FACE_X:
iter_E_PML_x_block(curBlock);
break;
case BLOCK_PML_FACE_Y:
iter_E_PML_y_block(curBlock);
break;
case BLOCK_PML_FACE_Z:
iter_E_PML_z_block(curBlock);
break;
default:
iter_E_PML_block(curBlock);
}
}
#ifdef HAVE_MPI
block_propagate_E(curBlock,b->blocks);
#endif
}
#ifdef HAVE_MPI
MPI_Waitall(b->mpi_blocks_before+b->mpi_blocks_after, mpi_reqs, MPI_STATUSES_IGNORE);
receive_E_msgs(b);
// MPI_Barrier(MPI_COMM_WORLD);
#endif
// Cartography output
for(i=0;ioutput->nb_cartos;i++)
if(iteration>=thesimul->output->cartos[i].begin && iterationoutput->cartos[i].end && (iteration-thesimul->output->cartos[i].begin)%thesimul->output->cartos[i].interv==0)
switch(thesimul->output->cartos[i].field)
{
case FIELD_E:
output_carto(b, thesimul->space, iteration, max_iteration, "E", FIELD_E, 1, output_buffer, field_buf);
break;
case FIELD_H:
output_carto(b, thesimul->space, iteration, max_iteration, "H", FIELD_H, cdtdx, output_buffer, field_buf);
break;
default:
panic("unknown field");
}
// Ponctual output
for(i=0;impi_node==b->mpi_node)
#endif
{
tmp_ponct = &(thesimul->output->poncts[i]);
switch(tmp_ponct->field)
{
case FIELD_E:
tmp_ponct->valx[iteration]=ponct_out_blocks[i]->Ex[ponct_out_offsets[i]];
tmp_ponct->valy[iteration]=ponct_out_blocks[i]->Ey[ponct_out_offsets[i]];
tmp_ponct->valz[iteration]=ponct_out_blocks[i]->Ez[ponct_out_offsets[i]];
break;
case FIELD_H:
tmp_ponct->valx[iteration]=ponct_out_blocks[i]->HHx[ponct_out_offsets[i]]*cdtdx;
tmp_ponct->valy[iteration]=ponct_out_blocks[i]->HHy[ponct_out_offsets[i]]*cdtdx;
tmp_ponct->valz[iteration]=ponct_out_blocks[i]->HHz[ponct_out_offsets[i]]*cdtdx;
break;
}
}
// Poynting output
for(i=0;ioutput->poynts[i]);
switch(tmp_poynt->dir)
{
case DIR_X:
tmp_poynt->val[iteration]=integ_poynt_x(tmp_poynt,poynt_out_init_blocks[i],b);
break;
case DIR_Y:
tmp_poynt->val[iteration]=integ_poynt_y(tmp_poynt,poynt_out_init_blocks[i],b);
break;
case DIR_Z:
tmp_poynt->val[iteration]=integ_poynt_z(tmp_poynt,poynt_out_init_blocks[i],b);
break;
}
}
}
// End of the main loop
time_end=get_time();
#ifdef HAVE_MPI
if(b->mpi_node == 0)
#endif
printf("\rSimulation took %.2f seconds. \nEach of the %i iterations took %.3f seconds.\n",time_end,max_iteration,(time_end-time_begin)/max_iteration);
free(output_buffer);
// Ponctual output
for(i=0;ioutput->poncts[i]);
#ifdef HAVE_MPI
// MPI_Barrier(MPI_COMM_WORLD);
if(b->mpi_node)
{
if(ponct_out_blocks[i]->mpi_node==b->mpi_node)
{
MPI_Send(tmp_ponct->valx, max_iteration, MPI_DOUBLE, 0,
TAG_PONCTOUT, MPI_COMM_WORLD);
MPI_Send(tmp_ponct->valy, max_iteration, MPI_DOUBLE, 0,
TAG_PONCTOUT, MPI_COMM_WORLD);
MPI_Send(tmp_ponct->valz, max_iteration, MPI_DOUBLE, 0,
TAG_PONCTOUT, MPI_COMM_WORLD);
}
continue;
}
else if(ponct_out_blocks[i]->mpi_node)
{
MPI_Recv(tmp_ponct->valx, max_iteration, MPI_DOUBLE,
ponct_out_blocks[i]->mpi_node,
TAG_PONCTOUT, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Recv(tmp_ponct->valy, max_iteration, MPI_DOUBLE,
ponct_out_blocks[i]->mpi_node,
TAG_PONCTOUT, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Recv(tmp_ponct->valz, max_iteration, MPI_DOUBLE,
ponct_out_blocks[i]->mpi_node,
TAG_PONCTOUT, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
#endif // HAVE_MPI
if(snprintf(filename,FILENAME_BUF-1,"%c_%i_%i_%i",(tmp_ponct->field==FIELD_E)?'E':'H',tmp_ponct->x,tmp_ponct->y,tmp_ponct->z)<0)
perror("ponct_output");
else
output_datfile3_fft(tmp_ponct->valx,tmp_ponct->valy,tmp_ponct->valz,max_iteration,filename,thesimul->simul->delta_t);
}
free(ponct_out_blocks);
free(ponct_out_offsets);
// Poynting output
free(poynt_out_init_blocks);
for(i=0;ioutput->poynts[i]);
int res=-1;
#ifdef HAVE_MPI
double *tmpdata=NULL;
if(b->mpi_node==0)
tmpdata=myalloc(max_iteration*sizeof(double));
MPI_Reduce(tmp_poynt->val, tmpdata, max_iteration, MPI_DOUBLE,
MPI_SUM, 0, MPI_COMM_WORLD);
if(b->mpi_node==0)
{
memcpy(tmp_poynt->val, tmpdata, max_iteration*sizeof(double));
free(tmpdata);
}
else
continue;
#endif // HAVE_MPI
switch(tmp_poynt->dir)
{
case DIR_X:
res=snprintf(filename,FILENAME_BUF-1,"poynt%i_x=%i",i,tmp_poynt->x1);
break;
case DIR_Y:
res=snprintf(filename,FILENAME_BUF-1,"poynt%i_y=%i",i,tmp_poynt->y1);
break;
case DIR_Z:
res=snprintf(filename,FILENAME_BUF-1,"poynt%i_z=%i",i,tmp_poynt->z1);
break;
}
if(res<0)
perror("poynt_output");
else
{
int cons=1;
if(thesimul->output->total_loss && i<6 && i%2==0)
cons=-1;
output_datfile_const(tmp_poynt->val,max_iteration,filename,thesimul->simul->delta_t,cons*cdtdx*SQUARE(thesimul->space->delta_x));
}
}
if(thesimul->output->total_loss
#ifdef HAVE_MPI
&& b->mpi_node==0
#endif
)
{
double *t=myalloc(max_iteration*sizeof(double));
for(i=0;ioutput->poynts[0].val[i]+thesimul->output->poynts[1].val[i]
-thesimul->output->poynts[2].val[i]+thesimul->output->poynts[3].val[i]
-thesimul->output->poynts[4].val[i]+thesimul->output->poynts[5].val[i];
output_datfile_const(t,max_iteration,"poynt_total",thesimul->simul->delta_t,cdtdx*SQUARE(thesimul->space->delta_x));
free(t);
}
#ifdef HAVE_MPI
for(i=0;impi_blocks_before;i++)
free(before_buffer[i]);
for(i=0;impi_blocks_after;i++)
free(after_buffer[i]);
free(mpi_buffers);
free(mpi_reqs);
#endif
destroy_blocklist(b);
return 0;
}
tessa-0.3.1/src/simul.h 0000644 0001750 0001750 00000000053 07751461506 011655 0000000 0000000 extern int RunSimul(SimulDesc *thesimul);
tessa-0.3.1/src/file.c 0000644 0001750 0001750 00000003525 07751455730 011447 0000000 0000000 /* Copyright (c) 2003 Ecole centrale de Lyon
*
* This program 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, version 2.
*
* 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "fdtd3d.h"
#include
#include
#include
#include "utils.h"
/* Reads the contents of a file.
Don't forget to free() the returned buffer. */
char *read_file(char *path)
{
FILE *thefile;
char *buffer;
int read_chars=0;
int bufsize=FILE_BUFFER;
int i;
thefile=fopen(path,"r");
if(thefile==NULL)
{
perror(path);
return NULL;
}
if((buffer=malloc(bufsize))==NULL)
panic("Not enough memory");
while((i=fread(buffer+read_chars,1,FILE_BUFFER,thefile))==FILE_BUFFER)
{
read_chars+=i;
if(read_chars+FILE_BUFFER>bufsize)
{
bufsize*=2;
buffer=realloc(buffer,bufsize);
}
}
fclose(thefile);
read_chars+=i;
buffer=realloc(buffer,read_chars+1);
buffer[read_chars]='\0';
return buffer;
}
/* Write in a file, overwriting it if necessary. */
int write_file(char *path,char *buffer)
{
FILE *thefile;
int i;
thefile=fopen(path,"w");
if(thefile==NULL)
{
perror(path);
return -1;
}
i=strlen(buffer);
if(fwrite(buffer,1,i,thefile)