Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add typemap for SourceTime and src_time #77

Merged
merged 2 commits into from
Aug 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions python/meep.i
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ extern boolean point_in_objectp(vector3 p, GEOMETRIC_OBJECT o);
PyObject *py_callback = NULL;

static PyObject *py_geometric_object();
static PyObject *py_source_time_object();
static PyObject* vec2py(const meep::vec &v);
static double py_callback_wrap(const meep::vec &v);
static int pyv3_to_v3(PyObject *po, vector3 *v);
Expand Down Expand Up @@ -152,6 +153,39 @@ static int py_list_to_gobj_list(PyObject *po, geometric_object_list *l);
delete[] $1.items;
}

// Typemap suite for sources

%typecheck(SWIG_TYPECHECK_POINTER) const meep::src_time & {
int py_source_time = PyObject_IsInstance($input, py_source_time_object());
int swig_src_time = PyObject_IsInstance($input, py_meep_src_time_object());

$1 = py_source_time || swig_src_time;
}

%typemap(in) const meep::src_time & {
PyObject *swig_obj = NULL;
void *tmp_ptr = 0;
int tmp_res = 0;

if(PyObject_IsInstance($input, py_source_time_object())) {
swig_obj = PyObject_GetAttrString($input, "swigobj");
Copy link
Collaborator

@stevengj stevengj Jul 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This returns a new reference, so you need to Py_DECREF(swig_obj) after the tmp_res = ... to avoid a memory leak.

However, swig_obj = $input does not create a new reference, so you will need a Py_INCREF(swig_obj) there to balance out the decref.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Fixed.

} else if(PyObject_IsInstance($input, py_meep_src_time_object())) {
swig_obj = $input;
Py_XINCREF(swig_obj);
} else {
PyErr_SetString(PyExc_TypeError, "Expected a meep.source.SourceTime or a meep.src_time\n");
SWIG_fail;
}

tmp_res = SWIG_ConvertPtr(swig_obj, &tmp_ptr, $1_descriptor, 0);
Py_XDECREF(swig_obj);

if(!SWIG_IsOK(tmp_res)) {
SWIG_exception_fail(SWIG_ArgError(tmp_res), "Couldn't convert Python object to meep::src_time");
}
$1 = reinterpret_cast<meep::src_time *>(tmp_ptr);
}

// Rename python builtins
%rename(br_apply) meep::boundary_region::apply;
%rename(_is) meep::dft_chunk::is;
Expand Down
2 changes: 1 addition & 1 deletion python/tests/test_bend_flux.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def bend_flux(no_bend):
df = 0.1
src = GaussianSource(fcen, df)
v = mp.volume(mp.vec(1.0 - 0.5 * sx, wvg_ycen), mp.vec(0.0, w))
f.add_volume_source(mp.Ez, src.swigobj, v)
f.add_volume_source(mp.Ez, src, v)

f_start = fcen - 0.5 * df
f_end = fcen + 0.5 * df
Expand Down
2 changes: 1 addition & 1 deletion python/tests/test_cyl_ellipsoid.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def main(args):
src = GaussianSource(fcen, df)
src_point = mp.vec(0.0, 0.0)
src_size = mp.vec(10.0, 10.0)
f.add_volume_source(src_cmpt, src.swigobj, mp.volume(src_point, src_size))
f.add_volume_source(src_cmpt, src, mp.volume(src_point, src_size))

f.output_hdf5(mp.Dielectric, f.total_volume())
stop_time = 23.0
Expand Down
2 changes: 1 addition & 1 deletion python/tests/test_physical.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def radiating_base(self, sq_ratio, solve_cw=True):
f = mp.fields(s)

src = ContinuousSource(w)
f.add_point_source(mp.Ez, src.swigobj, self.pnt_src_vec)
f.add_point_source(mp.Ez, src, self.pnt_src_vec)

# let the source reach steady state
if solve_cw:
Expand Down
2 changes: 1 addition & 1 deletion python/tests/test_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def main(args):
df = 0.1
src = GaussianSource(fcen, df)
v = mp.volume(mp.vec(r + 0.1, 0.0), mp.vec(0.0, 0.0))
f.add_volume_source(mp.Ez, src.swigobj, v)
f.add_volume_source(mp.Ez, src, v)

T = 300.0
stop_time = f.last_source_time() + T
Expand Down
49 changes: 47 additions & 2 deletions python/tests/test_source.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import unittest

from meep.geom import Vector3
from meep.source import EigenModeSource, ContinuousSource
import meep as mp
from meep.geom import Cylinder, Vector3
from meep.source import EigenModeSource, ContinuousSource, GaussianSource


class TestEigenModeSource(unittest.TestCase):
Expand All @@ -21,5 +22,49 @@ def test_eig_lattice_defaults(self):
self.assertEqual(custom_lattice.eig_lattice_center, elc)


class TestSourceTypemaps(unittest.TestCase):

expected_msg = "Expected a meep.source.SourceTime or a meep.src_time\n"

def setUp(self):

def dummy_eps(v):
return 1.0

gv = mp.voltwo(16, 16, 10)
gv.center_origin()
sym = mp.mirror(mp.Y, gv)
the_structure = mp.structure(gv, dummy_eps, mp.pml(2), sym)
objects = []
objects.append(Cylinder(1))
mp.set_materials_from_geometry(the_structure, objects)
self.f = mp.fields(the_structure)
self.v = mp.volume(mp.vec(1.1, 0.0), mp.vec(0.0, 0.0))

def test_typemap_swig(self):
src = mp.gaussian_src_time(0.15, 0.1)
self.f.add_volume_source(mp.Ez, src, self.v)

def test_typemap_py(self):
src = GaussianSource(0.15, 0.1)
self.f.add_volume_source(mp.Ez, src, self.v)

def test_typemap_swig_raises(self):
src = mp.gaussian_src_time(0.15, 0.1)
self.assertTrue(src.is_equal(src))

with self.assertRaises(TypeError) as error:
src.is_equal(mp.vec())
self.assertEqual(error.exception.message, self.expected_msg)

def test_typemap_py_raises(self):
src = GaussianSource(0.15, 0.1)
self.assertTrue(src.swigobj.is_equal(src))

with self.assertRaises(TypeError) as error:
src.swigobj.is_equal(Vector3())
self.assertEqual(error.exception.message, self.expected_msg)


if __name__ == '__main__':
unittest.main()
22 changes: 21 additions & 1 deletion python/typemap_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,33 @@
static PyObject *py_geometric_object() {
static PyObject *geometric_object = NULL;
if (geometric_object == NULL) {
PyObject *geom_mod = PyImport_ImportModule("geom");
PyObject *geom_mod = PyImport_ImportModule("meep.geom");
geometric_object = PyObject_GetAttrString(geom_mod, "GeometricObject");
Py_XDECREF(geom_mod);
}
return geometric_object;
}

static PyObject *py_source_time_object() {
static PyObject *source_time_object = NULL;
if (source_time_object == NULL) {
PyObject *source_mod = PyImport_ImportModule("meep.source");
source_time_object = PyObject_GetAttrString(source_mod, "SourceTime");
Py_XDECREF(source_mod);
}
return source_time_object;
}

static PyObject *py_meep_src_time_object() {
static PyObject *src_time = NULL;
if (src_time == NULL) {
PyObject *meep_mod = PyImport_ImportModule("meep");
src_time = PyObject_GetAttrString(meep_mod, "src_time");
Py_XDECREF(meep_mod);
}
return src_time;
}

static PyObject* vec2py(const meep::vec &v) {

double x = 0, y = 0, z = 0;
Expand Down