Skip to content

Commit

Permalink
fix[adjoint]: fix magnitude of gradient calculation in CustomMedium w…
Browse files Browse the repository at this point in the history
…hen permittivity and medium defined over different number of dimensions
  • Loading branch information
Gregory Roberts authored and Gregory Roberts committed Jan 16, 2025
1 parent 7c9f521 commit 5a4bfdb
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New field `min_steps_per_sim_size` in `AutoGrid` that sets minimal number of grid steps per longest edge length of simulation domain.
- Validation error in inverse design plugin when simulation has no sources by adding a source existence check before validating pixel size.
- System-dependent floating-point precision issue in EMEGrid validation.
- Fixed magnitude of gradient computation in `CustomMedium` by accounting properly for full volume element when permittivity data is defined over less dimensions than the medium.

## [2.8.0rc1] - 2024-12-17

Expand Down
27 changes: 17 additions & 10 deletions tidy3d/components/medium.py
Original file line number Diff line number Diff line change
Expand Up @@ -2648,7 +2648,17 @@ def _derivative_field_cmp(

coords_interp = {key: eps_data.coords[key] for key in "xyz"}
coords_interp = {key: val for key, val in coords_interp.items() if len(val) > 1}
dims_sum = [dim for dim in "xyz" if dim not in coords_interp]

E_der_dim_interp = E_der_map[f"E{dim}"]

for dim_ in "xyz":
if dim_ not in coords_interp:
bound_max = np.max(E_der_dim_interp.coords[dim_])
bound_min = np.min(E_der_dim_interp.coords[dim_])
dimension_size = bound_max - bound_min

if dimension_size > 0.0:
E_der_dim_interp = E_der_dim_interp.integrate(dim_)

# compute sizes along each of the interpolation dimensions
sizes_list = []
Expand Down Expand Up @@ -2676,27 +2686,24 @@ def _derivative_field_cmp(
d_vol = np.array(1.0)

# TODO: probably this could be more robust. eg if the DataArray has weird edge cases
E_der_dim = E_der_map[f"E{dim}"]
E_der_dim_interp = (
E_der_dim.interp(**coords_interp, assume_sorted=True).fillna(0.0).sum(dims_sum).real
E_der_dim_interp.interp(**coords_interp, assume_sorted=True).fillna(0.0).real.sum("f")
)
E_der_dim_interp = E_der_dim_interp.sum("f")

vjp_array = np.array(E_der_dim_interp.values, dtype=float)
vjp_array = vjp_array.reshape(eps_data.shape)

# multiply by volume elements (if possible, being defensive here..)
try:
vjp_array *= d_vol.reshape(vjp_array.shape)
E_der_dim_interp = E_der_dim_interp * d_vol.reshape(E_der_dim_interp.shape)
except ValueError:
log.warning(
"Skipping volume element normalization of 'CustomMedium' gradients. "
f"Could not reshape the volume elements of shape {d_vol.shape} "
f"to the shape of the gradient {vjp_array.shape}. "
f"to the shape of the fields {E_der_dim_interp.shape}. "
"If you encounter this warning, gradient direction will be accurate but the norm "
"will be inaccurate. Please raise an issue on the tidy3d front end with this "
"message and some information about your simulation setup and we will investigate. "
)
vjp_array = E_der_dim_interp.values
vjp_array = vjp_array.reshape(eps_data.shape)

return vjp_array


Expand Down

0 comments on commit 5a4bfdb

Please sign in to comment.