diff --git a/.travis.yml b/.travis.yml index ed9a8b8e4..85f1e07d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,6 +57,7 @@ matrix: - MKCHECKFLAGS="-j 2" - CPPFLAGS="${HDF5_SERIAL_CPPFLAGS} ${CPPFLAGS}" - LDFLAGS="${HDF5_SERIAL_LDFLAGS} ${LDFLAGS}" + - BUILD_WITHOUT_MPB="1" addons: apt: packages: @@ -164,6 +165,12 @@ script: make ${MKCHECKFLAGS} check && popd; fi + - > + if [[ "${BUILD_WITHOUT_MPB}" == "1" ]]; then + ../configure --enable-maintainer-mode --prefix=$HOME/local --with-libctl=$HOME/local/share/libctl ${MPICONF} ac_cv_header_mpb_h=no && + make clean && + make; + fi # Kill background sleep loop - kill %1 diff --git a/configure.ac b/configure.ac index 3e7d64041..064762796 100644 --- a/configure.ac +++ b/configure.ac @@ -525,7 +525,7 @@ else have_python=no],[#include ]) AC_MSG_CHECKING([for coverage module]) - $PYTHON -c 'import coverage' + $PYTHON -c 'import coverage' 2>/dev/null if test $? = 0; then AC_MSG_RESULT([yes]) have_coverage=yes diff --git a/python/Makefile.am b/python/Makefile.am index faef43dc7..b62aefe2f 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -7,14 +7,16 @@ HPPFILES= \ $(top_srcdir)/libmeepgeom/meepgeom.hpp \ $(top_srcdir)/libmeepgeom/material_data.hpp -BUILT_SOURCES = meep-python.cpp mpb-python.cpp __init__.py mpb.py -EXTRA_DIST = $(BUILT_SOURCES) typemap_utils.cpp solver.py mpb_data.py materials.py examples tests +BUILT_SOURCES = meep-python.cpp __init__.py +EXTRA_DIST = $(BUILT_SOURCES) typemap_utils.cpp materials.py examples tests CLEANFILES = $(BUILT_SOURCES) meep.py .coverage if WITH_MPB PYMPBINCLUDE=-I$(top_srcdir)/libpympb LIBPYMPB=$(top_builddir)/libpympb/libpympb.la + BUILT_SOURCES += mpb-python.cpp mpb.py + EXTRA_DIST += solver.py mpb_data.py endif LIBMEEPGEOM = $(top_builddir)/libmeepgeom/libmeepgeom.la @@ -30,10 +32,15 @@ _meep_la_LIBADD = $(LIBMEEP) $(LIBMEEPGEOM) $(PYTHON_LIBS) @LIBCTLGEOM_LIBS@ _meep_la_LDFLAGS = -module -version-info @SHARED_VERSION_INFO@ _meep_la_CPPFLAGS = $(PYTHON_INCLUDES) $(AM_CPPFLAGS) +if WITH_MPB _mpb_la_SOURCES = mpb-python.cpp _mpb_la_LIBADD = $(LIBMEEPGEOM) $(PYTHON_LIBS) $(LIBPYMPB) @LIBCTLGEOM_LIBS@ _mpb_la_LDFLAGS = -module -version-info @SHARED_VERSION_INFO@ _mpb_la_CPPFLAGS = $(PYTHON_INCLUDES) $(AM_CPPFLAGS) +MPB_LA = _mpb.la +endif # WITH_MPB + +TEST_DIR = tests # material_dispersion.py test must be excluded from test suite for MPI build if WITH_MPI @@ -41,16 +48,33 @@ if WITH_MPI MPBPYTEST= else MDPYTEST=$(TEST_DIR)/material_dispersion.py +if WITH_MPB MPBPYTEST=$(TEST_DIR)/mpb.py +else + MPBPYTEST= +endif # WITH_MPB +endif # WITH_MPI + +if WITH_MPB + BINARY_GRATING_TEST = $(TEST_DIR)/binary_grating.py + KDOM_TEST = $(TEST_DIR)/kdom.py + MODE_COEFFS_TEST = $(TEST_DIR)/mode_coeffs.py + MODE_DECOMPOSITION_TEST = $(TEST_DIR)/mode_decomposition.py + WVG_SRC_TEST = $(TEST_DIR)/wvg_src.py +else + BINARY_GRATING_TEST = + KDOM_TEST = + MODE_COEFFS_TEST = + MODE_DECOMPOSITION_TEST = + WVG_SRC_TEST = endif -TEST_DIR = tests TESTS = \ $(TEST_DIR)/3rd_harm_1d.py \ $(TEST_DIR)/absorber_1d.py \ $(TEST_DIR)/antenna_radiation.py \ $(TEST_DIR)/bend_flux.py \ - $(TEST_DIR)/binary_grating.py \ + $(BINARY_GRATING_TEST) \ $(TEST_DIR)/cavity_arrayslice.py \ $(TEST_DIR)/chunks.py \ $(TEST_DIR)/cyl_ellipsoid.py \ @@ -61,12 +85,12 @@ TESTS = \ $(TEST_DIR)/geom.py \ $(TEST_DIR)/holey_wvg_bands.py \ $(TEST_DIR)/holey_wvg_cavity.py \ - $(TEST_DIR)/kdom.py \ + $(KDOM_TEST) \ $(TEST_DIR)/ldos.py \ $(MDPYTEST) \ $(MPBPYTEST) \ - $(TEST_DIR)/mode_coeffs.py \ - $(TEST_DIR)/mode_decomposition.py \ + $(MODE_COEFFS_TEST) \ + $(MODE_DECOMPOSITION_TEST) \ $(TEST_DIR)/multilevel_atom.py \ $(TEST_DIR)/physical.py \ $(TEST_DIR)/pw_source.py \ @@ -76,7 +100,7 @@ TESTS = \ $(TEST_DIR)/simulation.py \ $(TEST_DIR)/source.py \ $(TEST_DIR)/user_defined_material.py \ - $(TEST_DIR)/wvg_src.py + $(WVG_SRC_TEST) if WITH_COVERAGE PY_LOG_COMPILER = coverage run -a --omit=$(top_srcdir)/python/tests/*,${HOME}/virtualenv/*,$(top_srcdir)/python/examples/* @@ -88,18 +112,22 @@ TEST_EXTENSIONS = .py TESTS_ENVIRONMENT = export PYTHONPATH=$(abs_top_builddir)/python:$$PYTHONPATH; if WITH_PYTHON - pympbdir = $(pkgpythondir)/mpb pkgpython_PYTHON = geom.py __init__.py source.py simulation.py materials.py pkgpyexec_LTLIBRARIES = _meep.la +if WITH_MPB + pympbdir = $(pkgpythondir)/mpb pympb_DATA = mpb.py solver.py mpb_data.py pympb_LTLIBRARIES = _mpb.la -endif +endif # WITH_MPB +endif # WITH_PYTHON +if WITH_MPB install-data-hook: mv $(DESTDIR)$(pkgpythondir)/mpb/mpb.py $(DESTDIR)$(pkgpythondir)/mpb/__init__.py uninstall-hook: rm -f $(DESTDIR)$(pkgpythondir)/mpb/__init__.py +endif if MAINTAINER_MODE @@ -110,32 +138,37 @@ MEEP_SWIG_SRC = meep.i numpy.i vec.i meep-python.cpp: $(MEEP_SWIG_SRC) $(HPPFILES) $(SWIG) -Wextra $(AM_CPPFLAGS) -outdir $(builddir) -c++ -python -o $@ $(srcdir)/meep.i +if WITH_MPB MPB_SWIG_SRC = mpb.i - mpb-python.cpp: $(MPB_SWIG_SRC) $(top_srcdir)/libpympb/pympb.hpp $(SWIG) -Wextra $(AM_CPPFLAGS) $(PYMPBINCLUDE) -outdir $(builddir) -c++ -python -o $@ $(srcdir)/mpb.i -meep.py: meep-python.cpp - mpb.py: mpb-python.cpp +MPB_PY = mpb.py +endif # WITH_MPB + +meep.py: meep-python.cpp -__init__.py: meep.py mpb.py +__init__.py: meep.py $(MPB_PY) cp $< $@ echo "__version__ = '$(shell git describe --tags | sed 's/^v//')'" >> $@ if [[ "${SWIG_VERSION}" = 3.0.12 ]]; then \ sed -i.bak '/^if _swig_python_version_info >= (2, 7, 0):/,/^else:/d' $@; \ sed -i.bak 's/ import _meep/from . import _meep/' $@; \ + fi +if WITH_MPB + if [[ "${SWIG_VERSION}" == 3.0.12 ]]; then \ sed -i.bak '/^if _swig_python_version_info >= (2, 7, 0):/,/^else:/d' mpb.py; \ sed -i.bak 's/ import _mpb/from . import _mpb/' mpb.py; \ fi - +endif INIT_PY = __init__.py -MPB_PY = $(builddir)/mpb.py +MPB_PY_PATH = $(builddir)/mpb.py else INIT_PY = $(srcdir)/__init__.py -MPB_PY = $(srcdir)/mpb.py +MPB_PY_PATH = $(srcdir)/mpb.py endif # MAINTAINER_MODE @@ -150,12 +183,15 @@ PY_PKG_FILES = \ $(HL_IFACE) \ .libs/_meep.so -meep: _meep.la _mpb.la __init__.py $(HL_IFACE) - mkdir -p meep/mpb +meep: _meep.la $(MPB_LA) __init__.py $(HL_IFACE) + mkdir -p meep cp $(PY_PKG_FILES) meep +if WITH_MPB + mkdir -p meep/mpb cp .libs/_mpb.so meep/mpb - cp $(MPB_PY) meep/mpb/__init__.py + cp $(MPB_PY_PATH) meep/mpb/__init__.py cp $(srcdir)/solver.py $(srcdir)/mpb_data.py meep/mpb +endif all-local: meep diff --git a/python/meep.i b/python/meep.i index 86848366d..457112aa6 100644 --- a/python/meep.i +++ b/python/meep.i @@ -17,6 +17,8 @@ %module meep +%import "config.h" + %{ #define SWIG_FILE_WITH_INIT #define SWIG_PYTHON_2_UNICODE @@ -24,31 +26,42 @@ #include #include +#include "config.h" #include "meep/vec.hpp" #include "meep.hpp" #include "meep/mympi.hpp" #include "ctl-math.h" #include "ctlgeom.h" #include "meepgeom.hpp" + +namespace meep { + size_t dft_chunks_Ntotal(dft_chunk *dft_chunks, size_t *my_start); + typedef std::complex (*amplitude_function)(const vec &); +} + +#ifdef HAVE_MPB #include "mpb.h" namespace meep { -size_t dft_chunks_Ntotal(dft_chunk *dft_chunks, size_t *my_start); -typedef std::complex (*amplitude_function)(const vec &); -struct eigenmode_data { - maxwell_data *mdata; - scalar_complex *fft_data_H, *fft_data_E; - evectmatrix H; - int n[3]; - double s[3]; - double Gk[3]; - vec center; - amplitude_function amp_func; - int band_num; - double omega; - double group_velocity; -}; + struct eigenmode_data { + maxwell_data *mdata; + scalar_complex *fft_data_H, *fft_data_E; + evectmatrix H; + int n[3]; + double s[3]; + double Gk[3]; + vec center; + amplitude_function amp_func; + int band_num; + double omega; + double group_velocity; + }; +} +#else +namespace meep { + struct eigenmode_data {}; } +#endif using namespace meep; using namespace meep_geom; @@ -56,7 +69,6 @@ using namespace meep_geom; extern boolean point_in_objectp(vector3 p, GEOMETRIC_OBJECT o); extern boolean point_in_periodic_objectp(vector3 p, GEOMETRIC_OBJECT o); void display_geometric_object_info(int indentby, GEOMETRIC_OBJECT o); - %} %include "numpy.i" @@ -431,42 +443,36 @@ kpoint_list get_eigenmode_coefficients_and_kpoints(meep::fields *f, meep::dft_fl return res; } -struct py_eigenmode_data { - void *data; - int band_num; - double omega; - double group_velocity; - PyObject *Gk; - PyObject *kdom; -}; - -py_eigenmode_data _get_eigenmode(meep::fields *f, double omega_src, meep::direction d, const meep::volume where, - const meep::volume eig_vol, int band_num, const meep::vec &_kpoint, - bool match_frequency, int parity, double resolution, double eigensolver_tol, - bool verbose) { +#ifdef HAVE_MPB +meep::eigenmode_data *_get_eigenmode(meep::fields *f, double omega_src, meep::direction d, const meep::volume where, + const meep::volume eig_vol, int band_num, const meep::vec &_kpoint, + bool match_frequency, int parity, double resolution, double eigensolver_tol, + bool verbose, double kdom[3]) { - double kdom[3]; void *data = f->get_eigenmode(omega_src, d, where, eig_vol, band_num, _kpoint, match_frequency, parity, resolution, eigensolver_tol, verbose, kdom); - meep::eigenmode_data *emdata = (meep::eigenmode_data *)data; - - py_eigenmode_data result = {}; - result.data = data; - result.band_num = emdata->band_num; - result.omega = emdata->omega; - result.group_velocity = emdata->group_velocity; + return (meep::eigenmode_data *)data; +} +PyObject *_get_eigenmode_Gk(meep::eigenmode_data *emdata) { PyObject *v3_class = py_vector3_object(); - PyObject *Gk_args = Py_BuildValue("(ddd)", emdata->Gk[0], emdata->Gk[1], emdata->Gk[2]); - PyObject *kdom_args = Py_BuildValue("(ddd)", kdom[0], kdom[1], kdom[2]); - result.Gk = PyObject_Call(v3_class, Gk_args, NULL); - result.kdom = PyObject_Call(v3_class, kdom_args, NULL); - - Py_DECREF(Gk_args); - Py_DECREF(kdom_args); - + PyObject *args = Py_BuildValue("(ddd)", emdata->Gk[0], emdata->Gk[1], emdata->Gk[2]); + PyObject *result = PyObject_Call(v3_class, args, NULL); + Py_DECREF(args); return result; } + +#else +void _get_eigenmode(meep::fields *f, double omega_src, meep::direction d, const meep::volume where, + const meep::volume eig_vol, int band_num, const meep::vec &_kpoint, + bool match_frequency, int parity, double resolution, double eigensolver_tol, + bool verbose, double kdom[3]) { + (void) f; (void) omega_src; (void) d; (void) where; (void) eig_vol; (void) band_num; (void) _kpoint; + (void) match_frequency; (void) parity; (void) resolution; (void) eigensolver_tol; + (void) verbose; (void) kdom; + meep::abort("Must compile Meep with MPB for get_eigenmode"); +} +#endif %} %numpy_typemaps(std::complex, NPY_CDOUBLE, int); @@ -804,6 +810,7 @@ meep::volume_list *make_volume_list(const meep::volume &v, int c, } %apply int INPLACE_ARRAY1[ANY] { int [3] }; +%apply double INPLACE_ARRAY1[ANY] { double [3] }; //-------------------------------------------------- // typemaps needed for get_eigenmode_coefficients @@ -1084,6 +1091,8 @@ meep::volume_list *make_volume_list(const meep::volume &v, int c, // it gets garbage collected and the file gets closed. %newobject meep::fields::open_h5file; +%newobject _get_eigenmode; + %rename(_vec) meep::vec::vec; %rename(_dft_ldos) meep::dft_ldos::dft_ldos; @@ -1148,17 +1157,44 @@ struct geom_box { vector3 high; }; -struct py_eigenmode_data { - void *data; +%rename(is_point_in_object) point_in_objectp(vector3 p, GEOMETRIC_OBJECT o); +%rename(is_point_in_periodic_object) point_in_periodic_objectp(vector3 p, GEOMETRIC_OBJECT o); + +#ifdef HAVE_MPB +namespace meep { +struct eigenmode_data { + maxwell_data *mdata; + scalar_complex *fft_data_H, *fft_data_E; + evectmatrix H; + int n[3]; + double s[3]; + double Gk[3]; + vec center; + amplitude_function amp_func; int band_num; double omega; double group_velocity; - PyObject *Gk; - PyObject *kdom; }; +} -%rename(is_point_in_object) point_in_objectp(vector3 p, GEOMETRIC_OBJECT o); -%rename(is_point_in_periodic_object) point_in_periodic_objectp(vector3 p, GEOMETRIC_OBJECT o); +meep::eigenmode_data *_get_eigenmode(meep::fields *f, double omega_src, meep::direction d, const meep::volume where, + const meep::volume eig_vol, int band_num, const meep::vec &_kpoint, + bool match_frequency, int parity, double resolution, double eigensolver_tol, + bool verbose, double kdom[3]); +PyObject *_get_eigenmode_Gk(meep::eigenmode_data *emdata); + +%extend meep::eigenmode_data { + ~eigenmode_data() { + meep::destroy_eigenmode_data($self); + } +} + +#else +void _get_eigenmode(meep::fields *f, double omega_src, meep::direction d, const meep::volume where, + const meep::volume eig_vol, int band_num, const meep::vec &_kpoint, + bool match_frequency, int parity, double resolution, double eigensolver_tol, + bool verbose, double kdom[3]); +#endif // HAVE_MPB extern boolean point_in_objectp(vector3 p, GEOMETRIC_OBJECT o); extern boolean point_in_periodic_objectp(vector3 p, GEOMETRIC_OBJECT o); @@ -1168,10 +1204,6 @@ kpoint_list get_eigenmode_coefficients_and_kpoints(meep::fields *f, meep::dft_fl int parity, double eig_resolution, double eigensolver_tol, std::complex *coeffs, double *vgrp, meep::kpoint_func user_kpoint_func, void *user_kpoint_data); -py_eigenmode_data _get_eigenmode(meep::fields *f, double omega_src, meep::direction d, const meep::volume where, - const meep::volume eig_vol, int band_num, const meep::vec &_kpoint, - bool match_frequency, int parity, double resolution, double eigensolver_tol, - bool verbose); %ignore eps_func; %ignore inveps_func; diff --git a/python/simulation.py b/python/simulation.py index 41394ec45..bdce98426 100644 --- a/python/simulation.py +++ b/python/simulation.py @@ -1389,11 +1389,13 @@ def get_eigenmode(self, omega_src, direction, where, band_num, kpoint, eig_vol=N eig_vol = self._volume_from_kwargs(vol=eig_vol) swig_kpoint = mp.vec(kpoint.x, kpoint.y, kpoint.z) + kdom = np.zeros(3) emdata = mp._get_eigenmode(self.fields, omega_src, direction, where, eig_vol, band_num, swig_kpoint, - match_frequency, parity, resolution, eigensolver_tol, verbose) + match_frequency, parity, resolution, eigensolver_tol, verbose, kdom) + Gk = mp._get_eigenmode_Gk(emdata) - return EigenmodeData(emdata.band_num, emdata.omega, emdata.group_velocity, emdata.Gk, - emdata.data, emdata.kdom) + return EigenmodeData(emdata.band_num, emdata.omega, emdata.group_velocity, Gk, + emdata, mp.Vector3(kdom[0], kdom[1], kdom[2])) def output_field_function(self, name, cs, func, real_only=False, h5file=None): if self.fields is None: diff --git a/python/vec.i b/python/vec.i index f45c68e29..09ad405d4 100644 --- a/python/vec.i +++ b/python/vec.i @@ -50,6 +50,7 @@ %warnfilter(451) meep::structure::outdir; %warnfilter(451) meep::fields_chunk::outdir; %warnfilter(325) meep::h5file::extending_s; +%warnfilter(509) _get_eigenmode; // Renaming python builtins %rename(meep_type) meep::type; diff --git a/src/mpb.cpp b/src/mpb.cpp index 68eb1ddd8..b725e4511 100644 --- a/src/mpb.cpp +++ b/src/mpb.cpp @@ -461,7 +461,7 @@ void *fields::get_eigenmode(double omega_src, /*--------------------------------------------------------------*/ /* do a second round of post-processing to tabulate E-fields -*/ /* on a (separate) internal storage buffer. (Previously -*/ - /* there was only one internal buffer which held either E-field * + /* there was only one internal buffer which held either E-field */ /* or H-field data, but this is inconvenient for cases in which */ /* you want the E and H fields of an eigenmode simultaneously.) */ /*--------------------------------------------------------------*/ @@ -714,7 +714,7 @@ void *fields::get_eigenmode(double omega_src, (void) omega_src; (void) d; (void) where; (void) eig_vol; (void) band_num; (void) kpoint; (void) match_frequency; (void) parity; (void) resolution; (void) eigensolver_tol; - (void) verbose (void) kdom; + (void) verbose; (void) kdom; abort("Meep must be configured/compiled with MPB for get_eigenmode"); } @@ -740,11 +740,12 @@ void fields::get_eigenmode_coefficients(dft_flux flux, double eig_resolution, double eigensolver_tol, std::complex *coeffs, double *vgrp, kpoint_func user_kpoint_func, - void *user_kpoint_data, vec *kpoints) + void *user_kpoint_data, vec *kpoints, vec *kdom) { (void) flux; (void) eig_vol; (void) bands; (void)num_bands; (void) parity; (void) eig_resolution; (void) eigensolver_tol; - (void) coeffs; (void) vgrp; (void) kpoints; (void) user_kpoint_func; (void) user_kpoint_data; + (void) coeffs; (void) vgrp; (void) kpoints; (void) user_kpoint_func; + (void) user_kpoint_data; (void) kdom; abort("Meep must be configured/compiled with MPB for get_eigenmode_coefficient"); }