Skip to content

Commit 252bbaf

Browse files
feat: warning for upcoming backward compatibility breaking unstructured=True (FXC-5123)
1 parent c433b1a commit 252bbaf

File tree

8 files changed

+91
-18
lines changed

8 files changed

+91
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818

1919
### Changed
2020
- `ModeSortSpec.sort_key` is now required with a default of `"n_eff"` (previously optional with `None` default). `ModeSortSpec.sort_order` is now optional with a default of `None`, which automatically selects the natural order based on `sort_key` and `sort_reference`: ascending when a reference is provided (closest first), otherwise descending for `n_eff` and polarization fractions (higher values first), ascending for `k_eff` and `mode_area` (lower values first).
21+
- Added deprecation warning for `TemperatureMonitor` and `SteadyPotentialMonitor` when `unstructured` parameter is not explicitly set. The default value of `unstructured` will change from `False` to `True` in the next release.
2122

2223
### Fixed
2324
- Fixed intermittent "API key not found" errors in parallel job launches by making configuration directory detection race-safe.

tests/test_components/test_heat_charge.py

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ def boundary_conditions():
232232
@pytest.fixture(scope="module")
233233
def monitors():
234234
"""Creates monitors of different types and sizes."""
235-
temp_mnt1 = td.TemperatureMonitor(size=(1.6, 2, 3), name="test")
235+
temp_mnt1 = td.TemperatureMonitor(size=(1.6, 2, 3), name="test", unstructured=False)
236236
temp_mnt2 = td.TemperatureMonitor(size=(1.6, 2, 3), name="tet", unstructured=True)
237237
temp_mnt3 = td.TemperatureMonitor(
238238
center=(0, 0.9, 0), size=(1.6, 0, 3), name="tri", unstructured=True, conformal=True
@@ -241,7 +241,7 @@ def monitors():
241241
center=(0, 0.9, 0), size=(1.6, 0, 3), name="empty", unstructured=True, conformal=False
242242
)
243243

244-
volt_mnt1 = td.SteadyPotentialMonitor(size=(1.6, 2, 3), name="v_test")
244+
volt_mnt1 = td.SteadyPotentialMonitor(size=(1.6, 2, 3), name="v_test", unstructured=False)
245245
volt_mnt2 = td.SteadyPotentialMonitor(size=(1.6, 2, 3), name="v_tet", unstructured=True)
246246
volt_mnt3 = td.SteadyPotentialMonitor(
247247
center=(0, 0.9, 0), size=(1.6, 0, 3), name="v_tri", unstructured=True, conformal=True
@@ -952,7 +952,7 @@ def test_freqs_validation():
952952
structures = [cathode, silicon, anode]
953953

954954
volt_monitor = td.SteadyPotentialMonitor(
955-
center=(0, 0, 0), size=(td.inf, td.inf, td.inf), name="voltage"
955+
center=(0, 0, 0), size=(td.inf, td.inf, td.inf), name="voltage", unstructured=False
956956
)
957957

958958
charge_tolerance = td.ChargeToleranceSpec(rel_tol=1e5, abs_tol=1e3, max_iters=400)
@@ -1137,6 +1137,42 @@ def test_vertical_natural_convection():
11371137
)
11381138

11391139

1140+
def test_unstructured_default_warning():
1141+
"""Test that warning is issued when unstructured uses default (not explicitly set)."""
1142+
# Should warn: unstructured not set (defaults to False)
1143+
with AssertLogLevel("WARNING", contains_str="default value of 'unstructured'"):
1144+
td.TemperatureMonitor(size=(1, 1, 1), name="test1")
1145+
1146+
# Should NOT warn: unstructured explicitly set to False
1147+
with AssertLogLevel(None):
1148+
td.TemperatureMonitor(size=(1, 1, 1), name="test2", unstructured=False)
1149+
1150+
# Should NOT warn: unstructured explicitly set to True
1151+
with AssertLogLevel(None):
1152+
td.TemperatureMonitor(size=(1, 1, 1), name="test3", unstructured=True)
1153+
1154+
# Should warn: SteadyPotentialMonitor with default unstructured (not explicitly set)
1155+
with AssertLogLevel("WARNING", contains_str="default value of 'unstructured'"):
1156+
td.SteadyPotentialMonitor(size=(1, 1, 1), name="test4")
1157+
1158+
# Should NOT warn: SteadyPotentialMonitor with unstructured explicitly set to False
1159+
with AssertLogLevel(None):
1160+
td.SteadyPotentialMonitor(size=(1, 1, 1), name="test5", unstructured=False)
1161+
1162+
# Should NOT warn: SteadyPotentialMonitor with unstructured explicitly set to True
1163+
with AssertLogLevel(None):
1164+
td.SteadyPotentialMonitor(size=(1, 1, 1), name="test6", unstructured=True)
1165+
1166+
# Should NOT warn: monitors with unstructured: Literal[True] (always unstructured=True)
1167+
with AssertLogLevel(None):
1168+
td.SteadyFreeCarrierMonitor(size=(1, 1, 1), name="test7")
1169+
td.SteadyEnergyBandMonitor(size=(1, 1, 1), name="test8")
1170+
td.SteadyCapacitanceMonitor(size=(1, 1, 1), name="test9")
1171+
td.SteadyElectricFieldMonitor(size=(1, 1, 1), name="test10")
1172+
td.SteadyCurrentDensityMonitor(size=(1, 1, 1), name="test11")
1173+
td.VolumeMeshMonitor(size=(1, 1, 1), name="test12")
1174+
1175+
11401176
def test_heat_charge_monitors_validation(monitors):
11411177
"""Checks for no name and negative size in monitors."""
11421178
temp_mnt = monitors[0]
@@ -1164,7 +1200,7 @@ def test_monitor_crosses_medium(mediums, structures, heat_simulation, conduction
11641200

11651201
# Voltage monitor
11661202
volt_monitor = td.SteadyPotentialMonitor(
1167-
center=(0, 0, 0), size=(td.inf, td.inf, td.inf), name="voltage"
1203+
center=(0, 0, 0), size=(td.inf, td.inf, td.inf), name="voltage", unstructured=False
11681204
)
11691205
# A voltage monitor in a heat simulation should throw error if no ChargeConductorMedium is present
11701206
with pytest.raises(pd.ValidationError):
@@ -1174,7 +1210,7 @@ def test_monitor_crosses_medium(mediums, structures, heat_simulation, conduction
11741210

11751211
# Temperature monitor
11761212
temp_monitor = td.TemperatureMonitor(
1177-
center=(0, 0, 0), size=(td.inf, td.inf, td.inf), name="temperature"
1213+
center=(0, 0, 0), size=(td.inf, td.inf, td.inf), name="temperature", unstructured=False
11781214
)
11791215
# A temperature monitor should throw error in a conduction simulation if no SolidSpec is present
11801216
with pytest.raises(pd.ValidationError):
@@ -1184,7 +1220,9 @@ def test_monitor_crosses_medium(mediums, structures, heat_simulation, conduction
11841220

11851221
# check error is raised in voltage monitor doesn't cross a conducting medium
11861222
with pytest.raises(pd.ValidationError):
1187-
volt_mnt = td.SteadyPotentialMonitor(center=(0, 0, 0), size=(0, td.inf, td.inf))
1223+
volt_mnt = td.SteadyPotentialMonitor(
1224+
center=(0, 0, 0), size=(0, td.inf, td.inf), unstructured=False
1225+
)
11881226
_ = conduction_simulation.updated_copy(monitors=[volt_mnt])
11891227

11901228

@@ -1365,7 +1403,7 @@ def test_sim_data_plotting(simulation_data):
13651403
heat_sim_data.updated_copy(data=[heat_sim_data.data[0]] * 2)
13661404

13671405
# Test updating simulation data with invalid simulation
1368-
temp_mnt = td.TemperatureMonitor(size=(1, 2, 3), name="test")
1406+
temp_mnt = td.TemperatureMonitor(size=(1, 2, 3), name="test", unstructured=False)
13691407
temp_mnt = temp_mnt.updated_copy(name="test2")
13701408

13711409
sim = heat_sim_data.simulation.updated_copy(monitors=[temp_mnt])
@@ -1797,6 +1835,7 @@ def place_box(center_offset):
17971835
center=[0, 0, 0],
17981836
size=(td.inf, td.inf, td.inf),
17991837
name="test_monitor",
1838+
unstructured=False,
18001839
)
18011840
],
18021841
)
@@ -1846,7 +1885,10 @@ def test_sim_structure_extent(box_size, log_level):
18461885
grid_spec=td.UniformUnstructuredGrid(dl=0.1),
18471886
monitors=[
18481887
td.SteadyPotentialMonitor(
1849-
center=(0, 0, 0), size=(td.inf, td.inf, td.inf), name="test_monitor"
1888+
center=(0, 0, 0),
1889+
size=(td.inf, td.inf, td.inf),
1890+
name="test_monitor",
1891+
unstructured=False,
18501892
)
18511893
],
18521894
)
@@ -1993,8 +2035,8 @@ def test_simulation_with_multiple_sources_and_monitors(
19932035
]
19942036

19952037
monitors = [
1996-
td.TemperatureMonitor(size=(1.6, 2, 3), name="temp_mnt1"),
1997-
td.SteadyPotentialMonitor(size=(1.6, 2, 3), name="volt_mnt1"),
2038+
td.TemperatureMonitor(size=(1.6, 2, 3), name="temp_mnt1", unstructured=False),
2039+
td.SteadyPotentialMonitor(size=(1.6, 2, 3), name="volt_mnt1", unstructured=False),
19982040
]
19992041

20002042
boundary_spec = [
@@ -2036,7 +2078,7 @@ def test_dynamic_simulation_updates(heat_simulation):
20362078
assert updated_sim.center == new_center
20372079

20382080
# Add a new monitor
2039-
new_monitor = td.TemperatureMonitor(size=(1, 1, 1), name="new_temp_mnt")
2081+
new_monitor = td.TemperatureMonitor(size=(1, 1, 1), name="new_temp_mnt", unstructured=False)
20402082
updated_sim = heat_simulation.updated_copy(
20412083
monitors=(*list(heat_simulation.monitors), new_monitor)
20422084
)
@@ -2242,7 +2284,7 @@ def test_bandgap_monitor():
22422284
def test_additional_edge_cases():
22432285
"""Test additional edge cases and error handling."""
22442286
# Attempt to create a monitor with zero size
2245-
td.TemperatureMonitor(size=(0, 0, 0), name="zero_size_mnt")
2287+
td.TemperatureMonitor(size=(0, 0, 0), name="zero_size_mnt", unstructured=False)
22462288

22472289
# Create a simulation with overlapping structures
22482290
td.HeatChargeSimulation(
@@ -2652,6 +2694,7 @@ def test_heat_charge_simulation_plot():
26522694
center=(0, 0, 0),
26532695
size=(1, 1, 0),
26542696
name="temp_mnt",
2697+
unstructured=False,
26552698
)
26562699

26572700
# Create a HEAT simulation

tidy3d/components/tcad/data/monitor_data/heat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class TemperatureData(HeatChargeMonitorData):
3737
>>> temp_data = SpatialDataArray(
3838
... np.ones((2, 3, 4)), coords={"x": [0, 1], "y": [0, 1, 2], "z": [0, 1, 2, 3]}
3939
... )
40-
>>> temp_mnt = TemperatureMonitor(size=(1, 2, 3), name="temperature")
40+
>>> temp_mnt = TemperatureMonitor(size=(1, 2, 3), name="temperature", unstructured=True)
4141
>>> temp_mnt_data = TemperatureData(
4242
... monitor=temp_mnt, temperature=temp_data, symmetry=(0, 1, 0), symmetry_center=(0, 0, 0)
4343
... )

tidy3d/components/tcad/data/sim_data.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class HeatChargeSimulationData(AbstractHeatChargeSimulationData):
221221
-------
222222
>>> import tidy3d as td
223223
>>> import numpy as np
224-
>>> temp_mnt = td.TemperatureMonitor(size=(1, 2, 3), name="sample")
224+
>>> temp_mnt = td.TemperatureMonitor(size=(1, 2, 3), name="sample", unstructured=True)
225225
>>> heat_sim = HeatChargeSimulation(
226226
... size=(3.0, 3.0, 3.0),
227227
... structures=[
@@ -506,7 +506,7 @@ class VolumeMesherData(AbstractHeatChargeSimulationData):
506506
>>> import tidy3d as td
507507
>>> import numpy as np
508508
>>> mesh_mnt = td.VolumeMeshMonitor(size=(1, 2, 3), name="mesh")
509-
>>> temp_mnt = td.TemperatureMonitor(size=(1, 2, 3), name="sample")
509+
>>> temp_mnt = td.TemperatureMonitor(size=(1, 2, 3), name="sample", unstructured=True)
510510
>>> heat_sim = td.HeatChargeSimulation(
511511
... size=(3.0, 3.0, 3.0),
512512
... structures=[

tidy3d/components/tcad/monitors/charge.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import pydantic.v1 as pd
88

99
from tidy3d.components.tcad.monitors.abstract import HeatChargeMonitor
10+
from tidy3d.log import log
1011

1112

1213
class SteadyPotentialMonitor(HeatChargeMonitor):
@@ -21,6 +22,19 @@ class SteadyPotentialMonitor(HeatChargeMonitor):
2122
... )
2223
"""
2324

25+
@pd.root_validator(pre=True)
26+
def _warn_unstructured_default_change(cls, values):
27+
"""Warn users that the default value of 'unstructured' will change to True in the next release."""
28+
# Only warn if 'unstructured' is not explicitly set (using default False)
29+
if "unstructured" not in values:
30+
log.warning(
31+
"The default value of 'unstructured' for 'SteadyPotentialMonitor' will change "
32+
"from 'False' to 'True' in the next release. To avoid this warning and ensure "
33+
"consistent behavior, please explicitly set 'unstructured=True' or 'unstructured=False' "
34+
"when creating the monitor."
35+
)
36+
return values
37+
2438

2539
class SteadyFreeCarrierMonitor(HeatChargeMonitor):
2640
"""

tidy3d/components/tcad/monitors/heat.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
from __future__ import annotations
44

5+
import pydantic.v1 as pd
56
from pydantic.v1 import Field, PositiveInt
67

78
from tidy3d.components.tcad.monitors.abstract import HeatChargeMonitor
9+
from tidy3d.log import log
810

911

1012
class TemperatureMonitor(HeatChargeMonitor):
@@ -19,3 +21,16 @@ class TemperatureMonitor(HeatChargeMonitor):
1921
"This can be useful for reducing data storage as needed by the application."
2022
"NOTE: this is only relevant for unsteady (transient) Heat simulations. ",
2123
)
24+
25+
@pd.root_validator(pre=True)
26+
def _warn_unstructured_default_change(cls, values):
27+
"""Warn users that the default value of 'unstructured' will change to True in the next release."""
28+
# Only warn if 'unstructured' is not explicitly set (using default False)
29+
if "unstructured" not in values:
30+
log.warning(
31+
"The default value of 'unstructured' for 'TemperatureMonitor' will change "
32+
"from 'False' to 'True' in the next release. To avoid this warning and ensure "
33+
"consistent behavior, please explicitly set 'unstructured=True' or 'unstructured=False' "
34+
"when creating the monitor."
35+
)
36+
return values

tidy3d/components/tcad/simulation/heat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class HeatSimulation(HeatChargeSimulation):
4343
... condition=td.TemperatureBC(temperature=500),
4444
... )
4545
... ],
46-
... monitors=[td.TemperatureMonitor(size=(1, 2, 3), name="sample")],
46+
... monitors=[td.TemperatureMonitor(size=(1, 2, 3), name="sample", unstructured=True)],
4747
... )
4848
"""
4949

tidy3d/components/tcad/simulation/heat_charge.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ class HeatChargeSimulation(AbstractSimulation):
228228
... condition=td.TemperatureBC(temperature=500),
229229
... )
230230
... ],
231-
... monitors=[td.TemperatureMonitor(size=(1, 2, 3), name="sample")],
231+
... monitors=[td.TemperatureMonitor(size=(1, 2, 3), name="sample", unstructured=True)],
232232
... )
233233
234234
To run a drift-diffusion (``Charge`` |:zap:|) system:
@@ -1999,7 +1999,7 @@ def from_scene(cls, scene: Scene, **kwargs: Any) -> HeatChargeSimulation:
19991999
... condition=TemperatureBC(temperature=500),
20002000
... )
20012001
... ],
2002-
... monitors=[TemperatureMonitor(name="temp_monitor", center=(0, 0, 0), size=(1, 1, 1))],
2002+
... monitors=[TemperatureMonitor(name="temp_monitor", center=(0, 0, 0), size=(1, 1, 1), unstructured=True)],
20032003
... )
20042004
"""
20052005

0 commit comments

Comments
 (0)