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

Various small changes while working on integration #92

Merged
merged 1 commit into from
Nov 19, 2021
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
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ max-line-length=100

[pre-commit-hook]
command=custom_pylint
disable=pointless-string-statement, too-many-ancestors, too-few-public-methods, fixme, logging-not-lazy, logging-fstring-interpolation, no-self-argument, no-self-use, duplicate-code
disable=pointless-string-statement, too-many-ancestors, too-few-public-methods, fixme, logging-not-lazy, logging-fstring-interpolation, no-self-argument, no-self-use, duplicate-code, unspecified-encoding
6 changes: 6 additions & 0 deletions tests/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,9 @@ def test_monitor_plane():
ModeMonitor(size=size, freqs=freqs, modes=[])
with pytest.raises(ValidationError) as e_info:
FluxMonitor(size=size, freqs=freqs, modes=[])


def test_freqs_nonempty():

with pytest.raises(ValidationError) as e_info:
FieldMonitor(size=(1, 1, 1), freqs=[])
3 changes: 2 additions & 1 deletion tidy3d/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
__version__ = "0.0.0"

from rich import pretty, traceback
from concurrent.futures import ProcessPoolExecutor

# import component as `from tidy3d import Simulation` or `td.Simulation`

Expand Down Expand Up @@ -63,4 +64,4 @@

# make all stdout and errors pretty
pretty.install()
traceback.install()
traceback.install(suppress=[ProcessPoolExecutor])
5 changes: 5 additions & 0 deletions tidy3d/components/grid.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Defines the FDTD grid."""
import numpy as np
from typing import List

from .base import Tidy3dBaseModel
from .types import Array, Axis
Expand Down Expand Up @@ -157,6 +158,10 @@ def sizes(self) -> Coords:
"""
return Coords(**{key: np.diff(val) for key, val in self.boundaries.dict().items()})

@property
def num_cells(self) -> List[int]:
return [coords1d.size - 1 for coords1d in self.boundaries.dict().values()]

@property
def _primal_steps(self) -> Coords:
"""Return primal steps of the cells in the :class:`Grid`.
Expand Down
9 changes: 8 additions & 1 deletion tidy3d/components/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .validators import assert_plane, validate_name_str
from .mode import Mode
from .viz import add_ax_if_none, MonitorParams
from ..log import SetupError
from ..log import SetupError, ValidationError


class Monitor(Box, ABC):
Expand Down Expand Up @@ -66,6 +66,13 @@ class FreqMonitor(Monitor, ABC):

freqs: Union[List[float], Array[float]]

@pydantic.validator("freqs", always=True)
def freqs_nonempty(cls, val):
"""Ensure freqs has at least one element"""
if len(val) == 0:
raise ValidationError("Monitor 'freqs' should have at least one element.")
return val


class TimeMonitor(Monitor, ABC):
"""Stores data in the time-domain."""
Expand Down
43 changes: 34 additions & 9 deletions tidy3d/components/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -767,8 +767,9 @@ def frequency_range(self) -> FreqBound:
Minumum and maximum frequencies of the power spectrum of the sources
at 5 standard deviations.
"""
freq_min = min(source.frequency_range[0] for source in self.sources)
freq_max = max(source.frequency_range[1] for source in self.sources)
source_ranges = [source.source_time.frequency_range for source in self.sources]
freq_min = min(freq_range[0] for freq_range in source_ranges)
freq_max = max(freq_range[1] for freq_range in source_ranges)
return (freq_min, freq_max)

""" Discretization """
Expand Down Expand Up @@ -866,8 +867,8 @@ def wvl_mat_min(self) -> float:
n_max, _ = AbstractMedium.eps_complex_to_nk(eps_max)
return wvl_min / n_max

def discretize(self, box: Box) -> Grid:
"""Grid containing only cells that intersect with a :class:`Box`.
def discretize_inds(self, box: Box) -> List[Tuple[int, int]]:
"""Start and stopping indexes for the cells that intersect with a :class:`Box`.

Parameters
----------
Expand All @@ -876,17 +877,18 @@ def discretize(self, box: Box) -> Grid:

Returns
-------
:class:`Grid`
The FDTD subgrid containing simulation points that intersect with ``box``.
List[Tuple[int, int]]
The (start, stop) indexes of the cells that intersect with ``box`` in each of the three
dimensions.
"""

if not self.intersects(box):
log.error(f"Box {box} is outside simulation, cannot discretize")

pts_min, pts_max = box.bounds
boundaries = self.grid.boundaries

# stores coords for subgrid
sub_cell_boundary_dict = {}
inds_list = []

# for each dimension
for axis_label, pt_min, pt_max in zip("xyz", pts_min, pts_max):
Expand All @@ -901,8 +903,31 @@ def discretize(self, box: Box) -> Grid:
inds_leq_pt_min = np.where(bound_coords <= pt_min)[0]
ind_min = 0 if len(inds_leq_pt_min) == 0 else inds_leq_pt_min[-1]

# store indexes
inds_list.append((ind_min, ind_max + 1))

return inds_list

def discretize(self, box: Box) -> Grid:
"""Grid containing only cells that intersect with a :class:`Box`.

Parameters
----------
box : :class:`Box`
Rectangular geometry within simulation to discretize.

Returns
-------
:class:`Grid`
The FDTD subgrid containing simulation points that intersect with ``box``.
"""

disc_inds = self.discretize_inds(box)
sub_cell_boundary_dict = {}
for axis_label, axis_inds in zip("xyz", disc_inds):
# copy orginal bound coords into subgrid coords
sub_cell_boundary_dict[axis_label] = bound_coords[ind_min : ind_max + 1]
bound_coords = self.grid.boundaries.dict()[axis_label]
sub_cell_boundary_dict[axis_label] = bound_coords[axis_inds[0] : axis_inds[1]]

# construct sub grid
sub_boundaries = Coords(**sub_cell_boundary_dict)
Expand Down
5 changes: 4 additions & 1 deletion tidy3d/components/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ def frequency_range(self) -> FreqBound:
:class:`GaussianPulse` or :class:`ContinuousWave` power
within 5 standard deviations.
"""
return (self.freq0 - WIDTH_STD * self.fwidth, self.freq0 + WIDTH_STD * self.fwidth)
width_std = 5
freq_min = max(0, self.freq0 - width_std * self.fwidth)
freq_max = self.freq0 + width_std * self.fwidth
return (freq_min, freq_max)


class GaussianPulse(Pulse):
Expand Down