Skip to content

Commit

Permalink
removed false positive warnings for bloch BC
Browse files Browse the repository at this point in the history
  • Loading branch information
tylerflex authored and momchil-flex committed Aug 30, 2024
1 parent 636746e commit 94d3284
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Error in `CustomSourceTime` when evaluating at a list of times entirely outside of the range of the envelope definition times.
- Improved passivity enforcement near high-Q poles in `FastDispersionFitter`. Failed passivity enforcement could lead to simulation divergences.
- More helpful error and suggestion if users try to differentiate w.r.t. unsupported `FluxMonitor` output.
- Removed positive warnings in Simulation validators for Bloch boundary conditions.

## [2.7.2] - 2024-08-07

Expand Down
2 changes: 1 addition & 1 deletion docs/notebooks
Submodule notebooks updated 116 files
9 changes: 9 additions & 0 deletions tests/test_components/test_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,14 @@ def test_validate_plane_wave_boundaries(log_capture):
angle_theta=np.pi / 4,
)

mnt = td.DiffractionMonitor(
center=(0, 0, 0),
size=(td.inf, td.inf, 0),
freqs=[250e12, 300e12],
name="monitor_diffraction",
normal_dir="+",
)

bspec1 = td.BoundarySpec(
x=td.Boundary.pml(),
y=td.Boundary.absorber(),
Expand Down Expand Up @@ -480,6 +488,7 @@ def test_validate_plane_wave_boundaries(log_capture):
run_time=1e-12,
sources=[src2],
boundary_spec=bspec3,
monitors=[mnt],
)

# angled incidence plane wave with wrong Bloch vector should warn
Expand Down
53 changes: 49 additions & 4 deletions tidy3d/components/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2323,6 +2323,46 @@ def plane_wave_boundaries(cls, val, values):
)
return val

@pydantic.validator("monitors", always=True)
@skip_if_fields_missing(["boundary_spec", "medium", "size", "structures", "sources"])
def bloch_boundaries_diff_mnt(cls, val, values):
"""Error if there are diffraction monitors incompatible with boundary conditions."""

monitors = val

if not val or not any(isinstance(mnt, DiffractionMonitor) for mnt in monitors):
return val

boundaries = values.get("boundary_spec").to_list
sources = values.get("sources")
size = values.get("size")
sim_medium = values.get("medium")
structures = values.get("structures")
for source_ind, source in enumerate(sources):
if not isinstance(source, PlaneWave):
continue

_, tan_dirs = cls.pop_axis([0, 1, 2], axis=source.injection_axis)
medium_set = Scene.intersecting_media(source, structures)
medium = medium_set.pop() if medium_set else sim_medium

for tan_dir in tan_dirs:
boundary = boundaries[tan_dir]

# check the Bloch boundary + angled plane wave case
num_bloch = sum(isinstance(bnd, (Periodic, BlochBoundary)) for bnd in boundary)
if num_bloch > 0:
cls._check_bloch_vec(
source=source,
source_ind=source_ind,
bloch_vec=boundary[0].bloch_vec,
dim=tan_dir,
medium=medium,
domain_size=size[tan_dir],
has_diff_mnt=True,
)
return val

@pydantic.validator("boundary_spec", always=True)
@skip_if_fields_missing(["medium", "center", "size", "structures", "sources"])
def tfsf_boundaries(cls, val, values):
Expand Down Expand Up @@ -3774,6 +3814,7 @@ def _check_bloch_vec(
dim: Axis,
medium: MediumType,
domain_size: float,
has_diff_mnt: bool = False,
):
"""Helper to check if a given Bloch vector is consistent with a given source."""

Expand All @@ -3786,23 +3827,27 @@ def _check_bloch_vec(
if bloch_vec != expected_bloch_vec:
test_val = np.real(expected_bloch_vec - bloch_vec)

if np.isclose(test_val % 1, 0) and not np.isclose(test_val, 0):
test_val_is_int = np.isclose(test_val, np.round(test_val))
src_name = f" '{source.name}'" if source.name else ""

if has_diff_mnt and test_val_is_int and not np.isclose(test_val, 0):
# the given Bloch vector is offset by an integer
log.warning(
f"The wave vector of source '{source.name}' along dimension "
f"The wave vector of source{src_name} along dimension "
f"'{dim}' is equal to the Bloch vector of the simulation "
"boundaries along that dimension plus an integer reciprocal "
"lattice vector. If using a 'DiffractionMonitor', diffraction "
"order 0 will not correspond to the angle of propagation "
"of the source. Consider using 'BlochBoundary.from_source()'.",
custom_loc=["boundary_spec", "xyz"[dim]],
)
elif not np.isclose(test_val % 1, 0):

if not test_val_is_int:
# the given Bloch vector is neither equal to the expected value, nor
# off by an integer
log.warning(
f"The Bloch vector along dimension '{dim}' may be incorrectly "
f"set with respect to the source '{source.name}'. The absolute "
f"set with respect to the source{src_name}. The absolute "
"difference between the expected and provided values in "
"bandstructure units, up to an integer offset, is greater than "
"1e-6. Consider using ``BlochBoundary.from_source()``, or "
Expand Down

0 comments on commit 94d3284

Please sign in to comment.