Skip to content

Commit

Permalink
apodization for frequency monitors
Browse files Browse the repository at this point in the history
  • Loading branch information
dbochkov-flexcompute committed Nov 15, 2022
1 parent c9be485 commit 76f7512
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 1 deletion.
2 changes: 1 addition & 1 deletion tests/sims/simulation_1_8_0.json

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions tests/test_components/test_apodization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Tests mode objects."""
import pytest
import pydantic
import tidy3d as td
from tidy3d.log import SetupError
import matplotlib.pylab as plt


def test_apodization():

a = td.ApodizationSpec(width=0.2)
a = td.ApodizationSpec(start=1, width=0.2)
a = td.ApodizationSpec(end=2, width=0.2)
a = td.ApodizationSpec(start=1, end=2, width=0.2)


def test_end_lt_start():
with pytest.raises(SetupError):
_ = td.ApodizationSpec(start=2, end=1, width=0.2)


def test_no_width():
with pytest.raises(pydantic.ValidationError):
_ = td.ApodizationSpec(start=1, end=2)


def test_negative_times():
with pytest.raises(pydantic.ValidationError):
_ = td.ApodizationSpec(start=-2, end=-1, width=0.2)

with pytest.raises(pydantic.ValidationError):
_ = td.ApodizationSpec(start=1, end=2, width=-0.2)

with pytest.raises(pydantic.ValidationError):
_ = td.ApodizationSpec(start=1, end=2, width=0)


def test_plot():

run_time = 1.0e-13
times = [0, 2.0e-14, 4.0e-14, 6.0e-14, 8.0e-14, 1.0e-13]

a = td.ApodizationSpec(start=0.2 * run_time, end=0.8 * run_time, width=0.02 * run_time)
a.plot(times)

fig, ax = plt.subplots(1, 1)
a.plot(times, ax=ax)
3 changes: 3 additions & 0 deletions tidy3d/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
# modes
from .components.mode import ModeSpec

# apodization
from .components.apodization import ApodizationSpec

# sources
from .components.source import GaussianPulse, ContinuousWave
from .components.source import UniformCurrentSource, PlaneWave, ModeSource, PointDipole
Expand Down
83 changes: 83 additions & 0 deletions tidy3d/components/apodization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""Defines specification for apodization."""

import pydantic as pd
import numpy as np

from .base import Tidy3dBaseModel
from ..constants import SECOND, inf
from ..log import SetupError
from .types import ArrayLike, Ax
from .viz import add_ax_if_none


class ApodizationSpec(Tidy3dBaseModel):
"""Stores specifications for the apodizaton of frequency monitors.
Example
-------
>>> apod_spec = ApodizationSpec(start=1, end=2, width=0.5)
"""

start: pd.NonNegativeFloat = pd.Field(
0.0,
title="Start Interval",
description="Defines the time at which the start apodization ends.",
units=SECOND,
)

end: pd.NonNegativeFloat = pd.Field(
inf,
title="End Interval",
description="Defines the time at which the end apodization begins.",
units=SECOND,
)

width: pd.PositiveFloat = pd.Field(
...,
title="Apodization Width",
description="Characteristic decay length of the apodization function.",
units=SECOND,
)

@pd.validator("end", always=True, allow_reuse=True)
def end_greater_than_start(cls, val, values):
"""Ensure sure end is greater than or equal to start."""
start = values.get("start")
if val and val < start:
raise SetupError("End apodization begins before start apodization ends.")
return val

@add_ax_if_none
def plot(self, times: ArrayLike[float, 1], ax: Ax = None) -> Ax:
"""Plot the apodization function.
Parameters
----------
times : np.ndarray
Array of times (seconds) to plot source at.
To see source time amplitude for a specific :class:`Simulation`,
pass ``simulation.tmesh``.
ax : matplotlib.axes._subplots.Axes = None
Matplotlib axes to plot on, if not specified, one is created.
Returns
-------
matplotlib.axes._subplots.Axes
The supplied or created matplotlib axes.
"""
times = np.array(times)
amp = np.ones_like(times)

start_ind = times < self.start
time_scaled = (times[start_ind] - self.start) / self.width
amp[start_ind] *= np.exp(-0.5 * time_scaled**2)

end_ind = times > self.end
time_scaled = (times[end_ind] - self.end) / self.width
amp[end_ind] *= np.exp(-0.5 * time_scaled**2)

ax.plot(times, amp, color="blueviolet")
ax.set_xlabel("time (s)")
ax.set_title("apodization function")
ax.set_aspect("auto")
return ax
7 changes: 7 additions & 0 deletions tidy3d/components/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .validators import assert_plane, validate_unique
from .base import cached_property
from .mode import ModeSpec
from .apodization import ApodizationSpec
from .viz import PlotParams, plot_params_monitor, ARROW_COLOR_MONITOR, ARROW_ALPHA
from ..constants import HERTZ, SECOND, MICROMETER, RADIAN, inf
from ..log import SetupError, log, ValidationError
Expand Down Expand Up @@ -74,6 +75,12 @@ class FreqMonitor(Monitor, ABC):
units=HERTZ,
)

apodization: ApodizationSpec = pydantic.Field(
ApodizationSpec(width=1),
title="Apodization Specification",
description="Sets parameters of (optional) apodization.",
)

@pydantic.validator("freqs", always=True)
def _freqs_non_empty(cls, val):
"""Assert one frequency present."""
Expand Down

0 comments on commit 76f7512

Please sign in to comment.