diff --git a/python/geom.py b/python/geom.py index a129cf1a7..335b70a98 100755 --- a/python/geom.py +++ b/python/geom.py @@ -529,7 +529,7 @@ class MaterialGrid(object): the `default_material` argument of the [`Simulation`](#Simulation) constructor (similar to a [material function](#medium)). """ - def __init__(self,grid_size,medium1,medium2,weights=None,grid_type="U_DEFAULT",do_averaging=False,beta=0,eta=0.5): + def __init__(self,grid_size,medium1,medium2,weights=None,grid_type="U_DEFAULT",do_averaging=False,beta=0,eta=0.5,damping=0): """ Creates a `MaterialGrid` object. @@ -563,11 +563,15 @@ def __init__(self,grid_size,medium1,medium2,weights=None,grid_type="U_DEFAULT",d grid values. Subpixel smoothing is fast and accurate because it exploits an analytic formulation for level-set functions. + A nonzero damping term creates an artificial conductivity σ = u(1-u)*damping, which acts as + dissipation loss that penalize intermediate pixel values of non-binarized structures. The value of + damping should be proportional to 2π times the typical frequency of the problem. + It is possible to overlap any number of different `MaterialGrid`s. This can be useful for defining grids which are symmetric (e.g., mirror, rotation). One way to set this up is by overlapping a given `MaterialGrid` object with a symmetrized copy of itself. In the case of spatially overlapping `MaterialGrid` objects (with no intervening objects), any overlapping points are computed using the - method `grid_type` which is one of `"U_MIN"` (minimum of the overlapping grid values), `"U_PROD"` + method `grid_type` which is one of `"U_MIN"` (minimum of the overlapping grid values), `"U_PROD"` (product), `"U_MEAN"` (mean), `"U_DEFAULT"` (topmost material grid). In general, these `"U_*"` options allow you to combine any material grids that overlap in space with no intervening objects. """ @@ -586,6 +590,7 @@ def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): self.do_averaging = do_averaging self.beta = beta self.eta = eta + self.damping = damping if weights is None: self.weights = np.zeros((self.num_params,)) elif weights.size != self.num_params: diff --git a/python/typemap_utils.cpp b/python/typemap_utils.cpp index 0602a72ff..e2182b3f8 100644 --- a/python/typemap_utils.cpp +++ b/python/typemap_utils.cpp @@ -581,11 +581,15 @@ static int pymaterial_to_material(PyObject *po, material_type *mt) { PyObject *py_eta = PyObject_GetAttrString(po, "eta"); double eta = 0; if (py_eta) { eta = PyFloat_AsDouble(py_eta); } - md = make_material_grid(do_averaging,beta,eta); + PyObject *py_damping = PyObject_GetAttrString(po, "damping"); + double damping = 0; + if (py_damping) { damping = PyFloat_AsDouble(py_damping); } + md = make_material_grid(do_averaging,beta,eta,damping); if (!pymaterial_grid_to_material_grid(po, md)) { return 0; } Py_XDECREF(py_do_averaging); Py_XDECREF(py_beta); Py_XDECREF(py_eta); + Py_XDECREF(py_damping); } else if (PyFunction_Check(po)) { PyObject *eps = PyObject_GetAttrString(po, "eps"); diff --git a/src/material_data.cpp b/src/material_data.cpp index 74e46d0cc..323c72eb4 100644 --- a/src/material_data.cpp +++ b/src/material_data.cpp @@ -86,6 +86,7 @@ void material_data::copy_from(const material_data &from) { medium_2 = from.medium_2; beta = from.beta; eta = from.eta; + damping = from.damping; } material_type_list::material_type_list() : items(NULL), num_items(0) {} diff --git a/src/material_data.hpp b/src/material_data.hpp index b219112c6..2fcbae81d 100644 --- a/src/material_data.hpp +++ b/src/material_data.hpp @@ -135,6 +135,7 @@ struct material_data { medium_struct medium_2; double beta; double eta; + double damping; /* There are several possible scenarios when material grids overlap -- these different scenarios enable different applications. @@ -180,7 +181,7 @@ extern material_type vacuum; material_type make_dielectric(double epsilon); material_type make_user_material(user_material_func user_func, void *user_data); material_type make_file_material(char *epsilon_input_file); -material_type make_material_grid(bool do_averaging, double beta, double eta); +material_type make_material_grid(bool do_averaging, double beta, double eta, double damping); void read_epsilon_file(const char *eps_input_file); void update_weights(material_type matgrid, double *weights); diff --git a/src/meepgeom.cpp b/src/meepgeom.cpp index f273ac55e..c914e8097 100644 --- a/src/meepgeom.cpp +++ b/src/meepgeom.cpp @@ -605,6 +605,10 @@ void epsilon_material_grid(material_data *md, double u) { // mm->D_conductivity_diag.x = mm->D_conductivity_diag.y = mm->D_conductivity_diag.z = u*(1-u) * // omega_mean; } + double fake_damping = u*(1-u)*(md->damping); + mm->D_conductivity_diag.x += fake_damping; + mm->D_conductivity_diag.y += fake_damping; + mm->D_conductivity_diag.z += fake_damping; } // return material of the point p from the file (assumed already read) @@ -1507,20 +1511,26 @@ static double get_cnd(meep::component c, const medium_struct *m) { } } +static bool has_conductivity(const material_type &md, meep::component c) { + medium_struct *mm; + if (is_medium(md, &mm) && get_cnd(c, mm)) return true; + if (md->which_subclass == material_data::MATERIAL_GRID && + (get_cnd(c, &md->medium_1) || get_cnd(c, &md->medium_2) || + md->damping != 0)) return true; + return false; +} + bool geom_epsilon::has_conductivity(meep::component c) { medium_struct *mm; FOR_DIRECTIONS(d) FOR_SIDES(b) { if (cond[d][b].prof) return true; } - for (int i = 0; i < geometry.num_items; ++i) - if (is_medium(geometry.items[i].material, &mm) && get_cnd(c, mm)) return true; - + if (meep_geom::has_conductivity((material_type) geometry.items[i].material, c)) return true; for (int i = 0; i < extra_materials.num_items; ++i) - if (is_medium(extra_materials.items[i], &mm) && get_cnd(c, mm)) return true; - - return (is_medium(default_material, &mm) && get_cnd(c, mm) != 0); + if (meep_geom::has_conductivity((material_type) extra_materials.items[i], c)) return true; + return meep_geom::has_conductivity((material_type) default_material, c); } static meep::vec geometry_edge; // geometry_lattice.size / 2 @@ -2024,12 +2034,13 @@ material_type make_file_material(const char *eps_input_file) { /******************************************************************************/ /* Material grid functions */ /******************************************************************************/ -material_type make_material_grid(bool do_averaging, double beta, double eta) { +material_type make_material_grid(bool do_averaging, double beta, double eta, double damping) { material_data *md = new material_data(); md->which_subclass = material_data::MATERIAL_GRID; md->do_averaging = do_averaging; md->beta = beta; md->eta = eta; + md->damping = damping; return md; } diff --git a/src/meepgeom.hpp b/src/meepgeom.hpp index f7617686e..bd723866e 100644 --- a/src/meepgeom.hpp +++ b/src/meepgeom.hpp @@ -246,7 +246,7 @@ void set_materials_from_geom_epsilon(meep::structure *s, geom_epsilon *geps, material_type make_dielectric(double epsilon); material_type make_user_material(user_material_func user_func, void *user_data, bool do_averaging); material_type make_file_material(const char *eps_input_file); -material_type make_material_grid(bool do_averaging, double beta, double eta); +material_type make_material_grid(bool do_averaging, double beta, double eta, double damping); vector3 vec_to_vector3(const meep::vec &pt); meep::vec vector3_to_vec(const vector3 v3);