diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bc752f12..fda2167a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- `TopologyDesignRegion` is now invariant in `z` by default and supports assigning dimensions along which a design should be uniform via `TopologyDesignRegion(uniform=(bool, bool, bool))`. + ### Fixed - Some validation fixes for design region. diff --git a/tests/test_plugins/test_invdes.py b/tests/test_plugins/test_invdes.py index 814fcb983..2088a0479 100644 --- a/tests/test_plugins/test_invdes.py +++ b/tests/test_plugins/test_invdes.py @@ -95,6 +95,18 @@ def test_region_params(): _ = design_region.params_zeros +def test_region_uniform(): + """Test parameter shape for uniform dimensions""" + region = make_design_region() + shape = region.params_shape + + test_region = region.updated_copy(uniform=(1, 1, 1)) + assert test_region.params_shape == (1, 1, 1) + + test_region = region.updated_copy(uniform=(1, 0, 1)) + assert test_region.params_shape == (1, *shape[1:]) + + def test_region_penalties(): """Test evaluation of penalties of a ``TopologyDesignRegion``.""" diff --git a/tidy3d/plugins/invdes/region.py b/tidy3d/plugins/invdes/region.py index 543adf658..5c60261c0 100644 --- a/tidy3d/plugins/invdes/region.py +++ b/tidy3d/plugins/invdes/region.py @@ -124,6 +124,13 @@ class TopologyDesignRegion(DesignRegion): "a value on the same order as the grid size.", ) + uniform: tuple[bool, bool, bool] = pd.Field( + (False, False, True), + title="Uniform", + description="Axes along which the design should be uniform. By default, the structure " + "is assumed to be uniform, i.e. invariant, in the z direction.", + ) + transformations: typing.Tuple[TransformationType, ...] = pd.Field( (), title="Transformations", @@ -166,12 +173,10 @@ def _check_params(params: anp.ndarray = None): @property def params_shape(self) -> typing.Tuple[int, int, int]: """Shape of the parameters array in (x, y, z), given the ``pixel_size`` and bounds.""" - # rmin, rmax = np.array(self.geometry.bounds) - # lengths = rmax - rmin side_lengths = np.array(self.size) num_pixels = np.ceil(side_lengths / self.pixel_size) # TODO: if the structure is infinite but the simulation is finite, need reduced bounds - num_pixels[np.isinf(num_pixels)] = 1 + num_pixels[np.logical_or(np.isinf(num_pixels), self.uniform)] = 1 return tuple(int(n) for n in num_pixels) def _warn_deprecate_params(self):