Skip to content

feat[adjoint]: Add conductivity gradient for CustomMedium #2582

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

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed
- Significantly improved performance of the `tidy3d.plugins.autograd.grey_dilation` morphological operation and its gradient calculation. The new implementation is orders of magnitude faster, especially for large arrays and kernel sizes.
- Support for gradients with respect to the `conductivity` of a `CustomMedium`.

### Fixed
- Arrow lengths are now scaled consistently in the X and Y directions, and their lengths no longer exceed the height of the plot window.
Expand Down
87 changes: 75 additions & 12 deletions tests/test_components/test_autograd.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,30 +315,42 @@ def make_structures(params: anp.ndarray) -> dict[str, td.Structure]:
eps_arr = 1.01 + 0.5 * (anp.tanh(matrix @ params).reshape(DA_SHAPE) + 1)

nx, ny, nz = eps_arr.shape
da_coords = {
"x": np.linspace(-0.5, 0.5, nx),
"y": np.linspace(-0.5, 0.5, ny),
"z": np.linspace(-0.5, 0.5, nz),
}

custom_med = td.Structure(
geometry=box,
medium=td.CustomMedium(
permittivity=td.SpatialDataArray(
eps_arr,
coords={
"x": np.linspace(-0.5, 0.5, nx),
"y": np.linspace(-0.5, 0.5, ny),
"z": np.linspace(-0.5, 0.5, nz),
},
coords=da_coords,
),
),
)

# custom medium with variable permittivity and conductivity data
conductivity_arr = 0.01 * (anp.tanh(matrix @ params).reshape(DA_SHAPE) + 1)
custom_med_with_conductivity = td.Structure(
geometry=box,
medium=td.CustomMedium(
permittivity=td.SpatialDataArray(
eps_arr,
coords=da_coords,
),
conductivity=td.SpatialDataArray(
conductivity_arr,
coords=da_coords,
),
),
)

# custom medium with vector valued permittivity data
eps_ii = td.ScalarFieldDataArray(
eps_arr.reshape(nx, ny, nz, 1),
coords={
"x": np.linspace(-0.5, 0.5, nx),
"y": np.linspace(-0.5, 0.5, ny),
"z": np.linspace(-0.5, 0.5, nz),
"f": [td.C_0],
},
coords=da_coords | {"f": [td.C_0]},
)

custom_med_vec = td.Structure(
Expand Down Expand Up @@ -480,6 +492,7 @@ def make_structures(params: anp.ndarray) -> dict[str, td.Structure]:
"center_list": center_list,
"size_element": size_element,
"custom_med": custom_med,
"custom_med_with_conductivity": custom_med_with_conductivity,
"custom_med_vec": custom_med_vec,
"polyslab": polyslab,
"polyslab_dispersive": polyslab_dispersive,
Expand Down Expand Up @@ -577,6 +590,7 @@ def plot_sim(sim: td.Simulation, plot_eps: bool = True) -> None:
"center_list",
"size_element",
"custom_med",
"custom_med_with_conductivity",
"custom_med_vec",
"polyslab",
"complex_polyslab",
Expand Down Expand Up @@ -1661,7 +1675,7 @@ def J(eps):
monkeypatch.setattr(
td.CustomPoleResidue,
"_derivative_field_cmp",
lambda self, E_der_map, eps_data, dim, freqs: dJ_deps / 3.0,
lambda self, E_der_map, eps_data, dim, freqs, component="real": dJ_deps / 3.0,
)

import importlib
Expand Down Expand Up @@ -2352,3 +2366,52 @@ def objective(x):

with pytest.raises(ValueError):
g = ag.grad(objective)(1.0)


def test_custom_medium_conductivity_only_gradient(rng, use_emulated_run, tmp_path):
"""Test conductivity gradients for CustomMedium with constant permittivity."""

monitor, postprocess = make_monitors()["field_point"]

def objective(params):
"""Objective function testing only conductivity gradient (constant permittivity)."""
len_arr = np.prod(DA_SHAPE)
matrix = rng.random((len_arr, N_PARAMS))

# constant permittivity
eps_arr = np.ones(DA_SHAPE) * 2.0

# variable conductivity
conductivity_arr = 0.05 * (anp.tanh(3 * matrix @ params).reshape(DA_SHAPE) + 1)

nx, ny, nz = DA_SHAPE
coords = {
"x": np.linspace(-0.5, 0.5, nx),
"y": np.linspace(-0.5, 0.5, ny),
"z": np.linspace(-0.5, 0.5, nz),
}

custom_med_struct = td.Structure(
geometry=td.Box(center=(0, 0, 0), size=(1, 1, 1)),
medium=td.CustomMedium(
permittivity=td.SpatialDataArray(eps_arr, coords=coords),
conductivity=td.SpatialDataArray(conductivity_arr, coords=coords),
),
)

sim = SIM_BASE.updated_copy(
structures=[custom_med_struct],
monitors=[monitor],
)

data = run(
sim,
path=str(tmp_path / "sim_test.hdf5"),
task_name="conductivity_only_grad_test",
verbose=False,
)
return postprocess(data, data[monitor.name])

val, grad = ag.value_and_grad(objective)(params0)

assert anp.all(grad != 0.0), "some gradients are 0 for conductivity-only test"
Loading
Loading