Skip to content

Commit 84a91a5

Browse files
feat(microwave): tidy3d_microwave and BroadbandPulse feature
1 parent 8b44dc5 commit 84a91a5

File tree

7 files changed

+139
-1
lines changed

7 files changed

+139
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
### Added
1212
- Added support for `tidy3d-extras`, an optional plugin that enables more accurate local mode solving via subpixel averaging.
1313
- Added support for `symlog` and `log` scale plotting in `Scene.plot_eps()` and `Scene.plot_structures_property()` methods. The `symlog` scale provides linear behavior near zero and logarithmic behavior elsewhere, while 'log' is a base 10 logarithmic scale.
14+
- Added support for `tidy3d-microwave`, a plugin enabling more microwave simulation features.
15+
- `BroadbandPulse` for injecting significant energy over entire the frequency range of interest.
1416

1517
### Changed
1618
- Improved performance of antenna metrics calculation by utilizing cached wave amplitude calculations instead of recomputing wave amplitudes for each port excitation in the `TerminalComponentModelerData`.

docs/api/sources.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Source Time Dependence
3434

3535
tidy3d.GaussianPulse
3636
tidy3d.ContinuousWave
37+
tidy3d.BroadbandPulse
3738
tidy3d.SourceTime
3839
tidy3d.CustomSourceTime
3940

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ devsim = { version = "*", optional = true }
117117
cma = { version = "*", optional = true }
118118
openpyxl = { version = "*", optional = true }
119119
# tidy3d-extras = { version = "2.10.0rc3", optional = true }
120+
# tidy3d-microwave = { version = "2.10.0rc3", optional = true }
120121

121122
[tool.poetry.extras]
122123
dev = [
@@ -212,6 +213,7 @@ heatcharge = ["trimesh", "vtk", "devsim"]
212213
pytorch = ["torch"]
213214
design = ["bayesian-optimization", "pygad", "pyswarms"]
214215
# extras = ["tidy3d-extras"]
216+
microwave = ["tidy3d-microwave"]
215217

216218
[tool.poetry.scripts]
217219
tidy3d = "tidy3d.web.cli:tidy3d_cli"

tests/test_components/test_packaging.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
Tidy3dImportError,
77
check_import,
88
supports_local_subpixel,
9+
supports_microwave,
910
tidy3d_extras,
11+
tidy3d_microwave,
1012
verify_packages_import,
1113
)
1214

@@ -90,5 +92,24 @@ def get_eps():
9092
get_eps()
9193

9294

95+
def test_tidy3d_microwave():
96+
import importlib
97+
98+
has_tidy3d_microwave = importlib.util.find_spec("tidy3d_microwave") is not None
99+
print(f"has_tidy3d_microwave = {has_tidy3d_microwave}")
100+
101+
if has_tidy3d_microwave:
102+
103+
@supports_microwave
104+
def get_pulse():
105+
assert tidy3d_microwave["mod"] is not None
106+
pulse = tidy3d_microwave["mod"].BroadbandPulse(fmin=0.1, fmax=10)
107+
_ = pulse.frequency_range(2)
108+
109+
get_pulse()
110+
else:
111+
assert tidy3d_microwave["mod"] is None
112+
113+
93114
if __name__ == "__main__":
94115
pytest.main()

tidy3d/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@
366366

367367
# sources
368368
from .components.source.time import (
369+
BroadbandPulse,
369370
ContinuousWave,
370371
CustomSourceTime,
371372
GaussianPulse,
@@ -466,6 +467,7 @@ def set_logging_level(level: str) -> None:
466467
"Box",
467468
"BroadbandModeABCFitterParam",
468469
"BroadbandModeABCSpec",
470+
"BroadbandPulse",
469471
"CaugheyThomasMobility",
470472
"CellDataArray",
471473
"ChargeConductorMedium",

tidy3d/components/source/time.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from tidy3d.constants import HERTZ
2222
from tidy3d.exceptions import ValidationError
2323
from tidy3d.log import log
24+
from tidy3d.packaging import supports_microwave, tidy3d_microwave
2425

2526
# how many units of ``twidth`` from the ``offset`` until a gaussian pulse is considered "off"
2627
END_TIME_FACTOR_GAUSSIAN = 10
@@ -605,4 +606,67 @@ def end_time(self) -> Optional[float]:
605606
return np.max(t_non_zero)
606607

607608

608-
SourceTimeType = Union[GaussianPulse, ContinuousWave, CustomSourceTime]
609+
class BroadbandPulse(SourceTime):
610+
"""A source time injecting significant energy in the entire custom frequency range."""
611+
612+
freq_range: FreqBound = pydantic.Field(
613+
...,
614+
title="Frequency Range",
615+
description="Frequency range where the pulse should have significant energy.",
616+
units=HERTZ,
617+
)
618+
minimum_amplitude: float = pydantic.Field(
619+
0.3,
620+
title="Minimum Amplitude",
621+
description="Minimum amplitude of the pulse relative to the peak amplitude in the frequency range.",
622+
gt=0.05,
623+
lt=0.5,
624+
)
625+
offset: float = pydantic.Field(
626+
5.0,
627+
title="Offset",
628+
description="Time delay of the maximum value of the "
629+
"pulse in units of 1 / (``2pi * fwidth``).",
630+
ge=2.5,
631+
)
632+
633+
@cached_property
634+
@supports_microwave
635+
def _source(self):
636+
"""Implementation of broadband pulse."""
637+
return tidy3d_microwave["mod"].BroadbandPulse(
638+
fmin=self.freq_range[0],
639+
fmax=self.freq_range[1],
640+
minRelAmp=self.minimum_amplitude,
641+
amp=self.amplitude,
642+
phase=self.phase,
643+
offset=self.offset,
644+
)
645+
646+
def end_time(self) -> float:
647+
"""Time after which the source is effectively turned off / close to zero amplitude."""
648+
return self._source.end_time(END_TIME_FACTOR_GAUSSIAN)
649+
650+
def amp_time(self, time: float) -> complex:
651+
"""Complex-valued source amplitude as a function of time."""
652+
return self._source.amp_time(time)
653+
654+
def amp_freq(self, freq: float) -> complex:
655+
"""Complex-valued source amplitude as a function of frequency."""
656+
return self._source.amp_freq(freq)
657+
658+
def frequency_range_sigma(self, sigma: float = DEFAULT_SIGMA) -> FreqBound:
659+
"""Frequency range where the source amplitude is within ``exp(-sigma**2/2)`` of the peak amplitude."""
660+
return self._source.frequency_range(sigma)
661+
662+
def frequency_range(self, num_fwidth: float = DEFAULT_SIGMA) -> FreqBound:
663+
"""Frequency range where the source amplitude is within ``exp(-sigma**2/2)`` of the peak amplitude."""
664+
return self.frequency_range_sigma(num_fwidth)
665+
666+
@cached_property
667+
def _freq0(self) -> float:
668+
"""Central frequency from frequency range."""
669+
return np.mean(self.freq_range)
670+
671+
672+
SourceTimeType = Union[GaussianPulse, ContinuousWave, CustomSourceTime, BroadbandPulse]

tidy3d/packaging.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
tidy3d_extras = {"mod": None, "use_local_subpixel": None}
2929

30+
tidy3d_microwave = {"mod": None}
31+
3032

3133
def check_import(module_name: str) -> bool:
3234
"""
@@ -249,3 +251,47 @@ def _fn(*args, **kwargs):
249251
return result
250252

251253
return _fn
254+
255+
256+
def supports_microwave(fn):
257+
"""When decorating a method, checks that 'tidy3d-microwave' is available."""
258+
259+
@functools.wraps(fn)
260+
def _fn(*args, **kwargs):
261+
# first try to import the module
262+
if tidy3d_microwave["mod"] is None:
263+
try:
264+
import tidy3d_microwave as tidy3d_microwave_mod
265+
266+
except ImportError as exc:
267+
tidy3d_microwave["mod"] = None
268+
raise Tidy3dImportError(
269+
"The package 'tidy3d-microwave' is required for this "
270+
"operation. "
271+
"Please install the 'tidy3d-microwave' package using, for "
272+
"example, 'pip install tidy3d[microwave]'."
273+
) from exc
274+
275+
else:
276+
version = tidy3d_microwave_mod.__version__
277+
278+
if version is None:
279+
tidy3d_microwave["mod"] = None
280+
raise Tidy3dImportError(
281+
"The package 'tidy3d-microwave' did not initialize correctly, "
282+
"likely due to an invalid API key."
283+
)
284+
285+
if version != __version__:
286+
log.warning(
287+
"The package 'tidy3d-microwave' is required for this "
288+
"operation. The version of 'tidy3d-microwave' should match "
289+
"the version of 'tidy3d'. You can install the correct "
290+
"version using 'pip install tidy3d[microwave]'."
291+
)
292+
293+
tidy3d_microwave["mod"] = tidy3d_microwave_mod
294+
295+
return fn(*args, **kwargs)
296+
297+
return _fn

0 commit comments

Comments
 (0)