From 5af42113f27dc93632c79374dc4f8101d8b23b82 Mon Sep 17 00:00:00 2001 From: Tyler Hughes Date: Thu, 29 Aug 2024 15:15:51 -0400 Subject: [PATCH] removed false positive warnings for bloch BC --- CHANGELOG.md | 1 + docs/faq | 2 +- docs/notebooks | 2 +- tests/test_components/test_simulation.py | 9 ++++ tidy3d/components/simulation.py | 53 ++++++++++++++++++++++-- 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fad77a1fe..37a749619 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/docs/faq b/docs/faq index 1a74c4b7c..9f577fe81 160000 --- a/docs/faq +++ b/docs/faq @@ -1 +1 @@ -Subproject commit 1a74c4b7cb1a1721fb0490e4510c0e30f0d03ac3 +Subproject commit 9f577fe81380ab45493187b59b5b95a0e163fe8e diff --git a/docs/notebooks b/docs/notebooks index 8735e5048..e8fcae49e 160000 --- a/docs/notebooks +++ b/docs/notebooks @@ -1 +1 @@ -Subproject commit 8735e504867f7dbd8a13579603b52802c6696b66 +Subproject commit e8fcae49eded1b6e9e4e91d7108d9a99f0613060 diff --git a/tests/test_components/test_simulation.py b/tests/test_components/test_simulation.py index c4093d12c..b68dea733 100644 --- a/tests/test_components/test_simulation.py +++ b/tests/test_components/test_simulation.py @@ -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(), @@ -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 diff --git a/tidy3d/components/simulation.py b/tidy3d/components/simulation.py index 33d5f368d..f2cb4ef28 100644 --- a/tidy3d/components/simulation.py +++ b/tidy3d/components/simulation.py @@ -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): @@ -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.""" @@ -3786,10 +3827,13 @@ 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 " @@ -3797,12 +3841,13 @@ def _check_bloch_vec( "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 "