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 optimization direction to invdes.Optimizer #1961

Merged
merged 1 commit into from
Sep 17, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for `dilation` argument in `JaxPolySlab`.
- Support for autograd differentiation with respect to `Cylinder.radius` and `Cylinder.center` (for elements not along axis dimension).
- `Cylinder.to_polyslab(num_pts_circumference, **kwargs)` to convert a cylinder into a discretized version represented by a `PolySlab`.
- `tidy3d.plugins.invdes.Optimizer` now accepts an optional optimization direction via the `maximize` argument (defaults to `maximize=True`).

### Changed
- `PolySlab` now raises error when differentiating and dilation causes damage to the polygon.
Expand Down
6 changes: 4 additions & 2 deletions tidy3d/plugins/invdes/design.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ class AbstractInverseDesign(InvdesBaseModel, abc.ABC):
)

def make_objective_fn(
self, post_process_fn: typing.Callable
self, post_process_fn: typing.Callable, maximize: bool = True
) -> typing.Callable[[anp.ndarray], tuple[float, dict]]:
"""construct the objective function for this ``InverseDesignMulti`` object."""

direction_multiplier = 1 if maximize else -1

def objective_fn(params: anp.ndarray, aux_data: dict = None) -> float:
"""Full objective function."""

Expand All @@ -52,7 +54,7 @@ def objective_fn(params: anp.ndarray, aux_data: dict = None) -> float:
post_process_val = post_process_fn(data)

penalty_value = self.design_region.penalty_value(params)
objective_fn_val = post_process_val - penalty_value
objective_fn_val = direction_multiplier * post_process_val - penalty_value

# store things in ``aux_data`` passed by reference
if aux_data is not None:
Expand Down
8 changes: 7 additions & 1 deletion tidy3d/plugins/invdes/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ class AbstractOptimizer(InvdesBaseModel, abc.ABC):
description="Step size for the gradient descent optimizer.",
)

maximize: bool = pd.Field(
True,
title="Direction of Optimization",
description="If ``True``, the optimizer will maximize the objective function. If ``False``, the optimizer will minimize the objective function.",
)

num_steps: pd.PositiveInt = pd.Field(
...,
title="Number of Steps",
Expand Down Expand Up @@ -103,7 +109,7 @@ def continue_run(
history = deepcopy(result.history)

# use autograd to take gradient the objective function
objective_fn = self.design.make_objective_fn(post_process_fn)
objective_fn = self.design.make_objective_fn(post_process_fn, maximize=self.maximize)
val_and_grad_fn = ag.value_and_grad(objective_fn)

# main optimization loop
Expand Down
Loading