diff --git a/CHANGELOG.md b/CHANGELOG.md index 061ba993b..0e75687be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Properties `num_time_steps_adjoint` and `tmesh_adjoint` to `JaxSimulation` to estimate adjoint run time. - Ability to add `path` to `updated_copy()` method to recursively update sub-components of a tidy3d model. For example `sim2 = sim.updated_copy(size=new_size, path="structures/0/geometry")` creates a recursively updated copy of `sim` where `sim.structures[0].geometry` is updated with `size=new_size`. - Python 3.12 support. Python 3.8 deprecation. Updated dependencies. +- A batch of `ModeSolver` objects can be run concurrently using `tidy3d.plugins.mode.web.run_batch()` ### Changed - IMPORTANT NOTE: differentiable fields in the `adjoint` plugin (`JaxBox.size`, `JaxBox.center`, `JaxPolySlab.vertices`) no longer store the derivative information after the object is initialized. For example, if using JaxPolySlab.vertices directly in an objective function, the vertices will have no effect on the gradient. Instead, this information is now stored in a field of the same name with `_jax` suffix, eg. `JaxPolySlab.vertices_jax`. For some applications, such as evaluating penalty values, please change to `radius_penalty.evaluate(polyslab.vertices_jax)` or use the vertices as generated by your parameterization functions (`make_vertices(params)`). diff --git a/scripts/sample.py b/scripts/sample.py index a516048a6..68aa3653b 100644 --- a/scripts/sample.py +++ b/scripts/sample.py @@ -1,4 +1,5 @@ """Generates sample simulation json and h5 files in the tests/sims folder""" + from os.path import join import sys diff --git a/tests/_test_data/_test_datasets_no_vtk.py b/tests/_test_data/_test_datasets_no_vtk.py index db06ef296..4c5e0b2ca 100644 --- a/tests/_test_data/_test_datasets_no_vtk.py +++ b/tests/_test_data/_test_datasets_no_vtk.py @@ -1,4 +1,5 @@ """Tests tidy3d/components/data/dataset.py""" + import pytest import builtins from ..test_data.test_datasets import test_triangular_dataset as _test_triangular_dataset diff --git a/tests/_test_local/_test_web.py b/tests/_test_local/_test_web.py index 72e8c60f6..785ac3db0 100644 --- a/tests/_test_local/_test_web.py +++ b/tests/_test_local/_test_web.py @@ -1,4 +1,5 @@ """ tests converted webapi """ + import os from unittest import TestCase, mock diff --git a/tests/test_cli/full_test_develop.py b/tests/test_cli/full_test_develop.py index 6600b4146..305aa0f83 100644 --- a/tests/test_cli/full_test_develop.py +++ b/tests/test_cli/full_test_develop.py @@ -1,6 +1,7 @@ """ These scripts just test the CLI commands for the develop command, and verify that they run properly. """ + import pytest import os from click.testing import CliRunner diff --git a/tests/test_components/test_IO.py b/tests/test_components/test_IO.py index 8a072c367..b1c36cdaf 100644 --- a/tests/test_components/test_IO.py +++ b/tests/test_components/test_IO.py @@ -1,4 +1,5 @@ """Tests file export and loading.""" + import os import json diff --git a/tests/test_components/test_apodization.py b/tests/test_components/test_apodization.py index 274e8b8c5..40a4017ad 100644 --- a/tests/test_components/test_apodization.py +++ b/tests/test_components/test_apodization.py @@ -1,4 +1,5 @@ """Tests mode objects.""" + import pytest import pydantic.v1 as pydantic import tidy3d as td diff --git a/tests/test_components/test_base.py b/tests/test_components/test_base.py index 7ad7e3684..88fc7069c 100644 --- a/tests/test_components/test_base.py +++ b/tests/test_components/test_base.py @@ -1,4 +1,5 @@ """Tests the base model.""" + import pytest import numpy as np diff --git a/tests/test_components/test_custom.py b/tests/test_components/test_custom.py index 9a5cbf54f..31452176b 100644 --- a/tests/test_components/test_custom.py +++ b/tests/test_components/test_custom.py @@ -1,4 +1,5 @@ """Tests custom sources and mediums.""" + import dill as pickle from typing import Tuple diff --git a/tests/test_components/test_field_projection.py b/tests/test_components/test_field_projection.py index 8e1208292..1c6e10e57 100644 --- a/tests/test_components/test_field_projection.py +++ b/tests/test_components/test_field_projection.py @@ -1,4 +1,5 @@ """Test near field to far field transformations.""" + import numpy as np import tidy3d as td import pytest diff --git a/tests/test_components/test_grid.py b/tests/test_components/test_grid.py index 1ea07d943..383d80eac 100644 --- a/tests/test_components/test_grid.py +++ b/tests/test_components/test_grid.py @@ -1,4 +1,5 @@ """Tests grid operations.""" + import pytest import numpy as np diff --git a/tests/test_components/test_grid_spec.py b/tests/test_components/test_grid_spec.py index 0a5ee6475..e9c5f5478 100644 --- a/tests/test_components/test_grid_spec.py +++ b/tests/test_components/test_grid_spec.py @@ -1,4 +1,5 @@ """Tests GridSpec.""" + import pytest import numpy as np diff --git a/tests/test_components/test_medium.py b/tests/test_components/test_medium.py index 4eba082b1..12d4a107b 100644 --- a/tests/test_components/test_medium.py +++ b/tests/test_components/test_medium.py @@ -1,4 +1,5 @@ """Tests mediums.""" + import numpy as np import pytest import pydantic.v1 as pydantic diff --git a/tests/test_components/test_meshgenerate.py b/tests/test_components/test_meshgenerate.py index 22e108b41..78c8af2b9 100644 --- a/tests/test_components/test_meshgenerate.py +++ b/tests/test_components/test_meshgenerate.py @@ -1,4 +1,5 @@ """Tests generating meshes.""" + import numpy as np import warnings import pytest diff --git a/tests/test_components/test_mode.py b/tests/test_components/test_mode.py index 8363fde22..88a58e195 100644 --- a/tests/test_components/test_mode.py +++ b/tests/test_components/test_mode.py @@ -1,4 +1,5 @@ """Tests mode objects.""" + import pytest import pydantic.v1 as pydantic import numpy as np diff --git a/tests/test_components/test_monitor.py b/tests/test_components/test_monitor.py index 632634e7a..93b4f22b0 100644 --- a/tests/test_components/test_monitor.py +++ b/tests/test_components/test_monitor.py @@ -1,4 +1,5 @@ """Tests monitors.""" + import pytest import pydantic.v1 as pydantic import numpy as np diff --git a/tests/test_components/test_parameter_perturbation.py b/tests/test_components/test_parameter_perturbation.py index 60d455073..c1cc7a470 100644 --- a/tests/test_components/test_parameter_perturbation.py +++ b/tests/test_components/test_parameter_perturbation.py @@ -1,4 +1,5 @@ """Tests parameter perturbations.""" + import numpy as np import matplotlib.pyplot as plt import pytest diff --git a/tests/test_components/test_scene.py b/tests/test_components/test_scene.py index e095f99d7..26a7415be 100644 --- a/tests/test_components/test_scene.py +++ b/tests/test_components/test_scene.py @@ -1,4 +1,5 @@ """Tests the scene and its validators.""" + import pytest import pydantic.v1 as pd import matplotlib.pyplot as plt diff --git a/tests/test_components/test_sidewall.py b/tests/test_components/test_sidewall.py index 42f4c0de7..12b6d87b2 100644 --- a/tests/test_components/test_sidewall.py +++ b/tests/test_components/test_sidewall.py @@ -1,4 +1,5 @@ """test slanted polyslab can be correctly setup and visualized. """ + import pytest import numpy as np import pydantic.v1 as pydantic diff --git a/tests/test_components/test_simulation.py b/tests/test_components/test_simulation.py index f3f206981..aba5ab33d 100644 --- a/tests/test_components/test_simulation.py +++ b/tests/test_components/test_simulation.py @@ -1,4 +1,5 @@ """Tests the simulation and its validators.""" + import pytest import pydantic.v1 as pydantic import matplotlib.pyplot as plt diff --git a/tests/test_components/test_source.py b/tests/test_components/test_source.py index e9b612643..9634904a5 100644 --- a/tests/test_components/test_source.py +++ b/tests/test_components/test_source.py @@ -1,4 +1,5 @@ """Tests sources.""" + import pytest import pydantic.v1 as pydantic import matplotlib.pyplot as plt diff --git a/tests/test_components/test_time_modulation.py b/tests/test_components/test_time_modulation.py index 4080c6ab4..3931a744a 100644 --- a/tests/test_components/test_time_modulation.py +++ b/tests/test_components/test_time_modulation.py @@ -1,4 +1,5 @@ """Tests space time modulation.""" + import numpy as np import pytest from math import isclose diff --git a/tests/test_components/test_types.py b/tests/test_components/test_types.py index 3332ddc8b..09ede00f7 100644 --- a/tests/test_components/test_types.py +++ b/tests/test_components/test_types.py @@ -1,4 +1,5 @@ """Tests type definitions.""" + import pytest import pydantic.v1 as pydantic from tidy3d.components.types import ArrayLike, Complex, constrained_array, Tuple diff --git a/tests/test_components/test_viz.py b/tests/test_components/test_viz.py index 6f4085d0b..be1979a98 100644 --- a/tests/test_components/test_viz.py +++ b/tests/test_components/test_viz.py @@ -1,4 +1,5 @@ """Tests visualization operations.""" + import pytest import matplotlib.pyplot as plt import tidy3d as td diff --git a/tests/test_data/test_data_arrays.py b/tests/test_data/test_data_arrays.py index 83c1378f0..81c0479c4 100644 --- a/tests/test_data/test_data_arrays.py +++ b/tests/test_data/test_data_arrays.py @@ -1,4 +1,5 @@ """Tests tidy3d/components/data/data_array.py""" + import pytest import numpy as np from typing import Tuple, List diff --git a/tests/test_data/test_datasets.py b/tests/test_data/test_datasets.py index 9d160d5af..abad90ee7 100644 --- a/tests/test_data/test_datasets.py +++ b/tests/test_data/test_datasets.py @@ -1,4 +1,5 @@ """Tests tidy3d/components/data/dataset.py""" + import pytest import numpy as np import pydantic.v1 as pd diff --git a/tests/test_data/test_monitor_data.py b/tests/test_data/test_monitor_data.py index 708cebf1a..2f05a8449 100644 --- a/tests/test_data/test_monitor_data.py +++ b/tests/test_data/test_monitor_data.py @@ -1,4 +1,5 @@ """Tests tidy3d/components/data/monitor_data.py""" + import numpy as np import matplotlib.pyplot as plt import pytest diff --git a/tests/test_data/test_sim_data.py b/tests/test_data/test_sim_data.py index ef29c186c..2713b42f5 100644 --- a/tests/test_data/test_sim_data.py +++ b/tests/test_data/test_sim_data.py @@ -1,4 +1,5 @@ """Tests SimulationData""" + import pytest import numpy as np import matplotlib.pyplot as plt diff --git a/tests/test_package/test_make_script.py b/tests/test_package/test_make_script.py index 57ffb9bb6..d81ae55fd 100644 --- a/tests/test_package/test_make_script.py +++ b/tests/test_package/test_make_script.py @@ -1,4 +1,5 @@ """Tests generation of pythons script from simulation file.""" + import tidy3d as td from make_script import main diff --git a/tests/test_plugins/test_design.py b/tests/test_plugins/test_design.py index 49431830e..4297e57b0 100644 --- a/tests/test_plugins/test_design.py +++ b/tests/test_plugins/test_design.py @@ -1,4 +1,5 @@ """Test the parameter sweep plugin.""" + import pytest import numpy as np import tidy3d as td diff --git a/tests/test_plugins/test_mode_solver.py b/tests/test_plugins/test_mode_solver.py index 1b8bc3c05..78c2d5efa 100644 --- a/tests/test_plugins/test_mode_solver.py +++ b/tests/test_plugins/test_mode_solver.py @@ -15,6 +15,7 @@ from ..utils import assert_log_level, log_capture, cartesian_to_unstructured # noqa: F401 from tidy3d import ScalarFieldDataArray from tidy3d.web.core.environment import Env +from tidy3d.components.data.monitor_data import ModeSolverData WG_MEDIUM = td.Medium(permittivity=4.0, conductivity=1e-4) @@ -836,3 +837,43 @@ def test_mode_solver_method_defaults(): sim = ms.sim_with_monitor(name="test") assert np.allclose(sim.monitors[-1].freqs, ms.freqs) + + +def test_mode_solver_web_run_batch(): + """Testing run_batch function for the web mode solver.""" + wav = 1.5 + wav_min = 1.4 + wav_max = 1.5 + num_freqs = 5 + num_of_sims = 3 + freqs = np.linspace(td.C_0 / wav_min, td.C_0 / wav_max, num_freqs) + + simulation = td.Simulation( + size=SIM_SIZE, + grid_spec=td.GridSpec(wavelength=wav), + structures=[WAVEGUIDE], + run_time=1e-12, + boundary_spec=td.BoundarySpec.all_sides(boundary=td.PML()), + ) + + # create a list of mode solvers + mode_solver_list = [None] * num_of_sims + + # create three different mode solvers with different number of modes specifications + for i in range(num_of_sims): + mode_solver_list[i] = ModeSolver( + simulation=simulation, + plane=PLANE, + mode_spec=td.ModeSpec( + num_modes=i + 1, + target_neff=2.0, + ), + freqs=freqs, + direction="+", + ) + + # Run mode solver one at a time + results = msweb.run_batch(mode_solver_list, verbose=False) + + assert all(isinstance(x, ModeSolverData) for x in results) + assert (results[i].n_eff.shape == (num_freqs, i + 1) for i in range(num_of_sims)) diff --git a/tidy3d/__main__.py b/tidy3d/__main__.py index b0ffe5e5d..d7613d1e6 100644 --- a/tidy3d/__main__.py +++ b/tidy3d/__main__.py @@ -1,4 +1,5 @@ """ command-line interface. For instructions run `python -m tidy3d --help` """ + import sys import argparse diff --git a/tidy3d/components/base.py b/tidy3d/components/base.py index eb118144e..2644cec6e 100644 --- a/tidy3d/components/base.py +++ b/tidy3d/components/base.py @@ -1,4 +1,5 @@ """global configuration / base class for pydantic models used to make simulation.""" + from __future__ import annotations import json diff --git a/tidy3d/components/base_sim/data/monitor_data.py b/tidy3d/components/base_sim/data/monitor_data.py index fffcf130c..47b5b99c1 100644 --- a/tidy3d/components/base_sim/data/monitor_data.py +++ b/tidy3d/components/base_sim/data/monitor_data.py @@ -1,4 +1,5 @@ """Abstract base for monitor data structures.""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/base_sim/data/sim_data.py b/tidy3d/components/base_sim/data/sim_data.py index f782e1ecf..9bee2e39a 100644 --- a/tidy3d/components/base_sim/data/sim_data.py +++ b/tidy3d/components/base_sim/data/sim_data.py @@ -1,4 +1,5 @@ """Abstract base for simulation data structures.""" + from __future__ import annotations from typing import Dict, Tuple, Union diff --git a/tidy3d/components/base_sim/monitor.py b/tidy3d/components/base_sim/monitor.py index ff13887fd..7e6ce362e 100644 --- a/tidy3d/components/base_sim/monitor.py +++ b/tidy3d/components/base_sim/monitor.py @@ -1,4 +1,5 @@ """Abstract bases for classes that define how data is recorded from simulation.""" + from abc import ABC, abstractmethod from typing import Tuple diff --git a/tidy3d/components/base_sim/simulation.py b/tidy3d/components/base_sim/simulation.py index 418dfddb9..3695b39d7 100644 --- a/tidy3d/components/base_sim/simulation.py +++ b/tidy3d/components/base_sim/simulation.py @@ -1,4 +1,5 @@ """Abstract base for defining simulation classes of different solvers""" + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/components/base_sim/source.py b/tidy3d/components/base_sim/source.py index d2089523b..5066298dc 100644 --- a/tidy3d/components/base_sim/source.py +++ b/tidy3d/components/base_sim/source.py @@ -1,4 +1,5 @@ """Abstract base for classes that define simulation sources.""" + from __future__ import annotations from abc import ABC, abstractmethod import pydantic.v1 as pydantic diff --git a/tidy3d/components/bc_placement.py b/tidy3d/components/bc_placement.py index 5b48a77c1..5d056ee9b 100644 --- a/tidy3d/components/bc_placement.py +++ b/tidy3d/components/bc_placement.py @@ -1,4 +1,5 @@ """Defines placements for boundary conditions.""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/boundary.py b/tidy3d/components/boundary.py index 372cac445..92202c09c 100644 --- a/tidy3d/components/boundary.py +++ b/tidy3d/components/boundary.py @@ -1,4 +1,5 @@ """Defines electromagnetic boundary conditions""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/data/data_array.py b/tidy3d/components/data/data_array.py index f559c3eb8..0c1589a2a 100644 --- a/tidy3d/components/data/data_array.py +++ b/tidy3d/components/data/data_array.py @@ -1,4 +1,5 @@ """Storing tidy3d data at it's most fundamental level as xr.DataArray objects""" + from __future__ import annotations from typing import Dict, List, Union from abc import ABC diff --git a/tidy3d/components/data/dataset.py b/tidy3d/components/data/dataset.py index 94524dd7f..d4438a42c 100644 --- a/tidy3d/components/data/dataset.py +++ b/tidy3d/components/data/dataset.py @@ -1,4 +1,5 @@ """Collections of DataArrays.""" + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/components/data/monitor_data.py b/tidy3d/components/data/monitor_data.py index 704986b4b..52648a93e 100644 --- a/tidy3d/components/data/monitor_data.py +++ b/tidy3d/components/data/monitor_data.py @@ -1,4 +1,5 @@ """ Monitor Level Data, store the DataArrays associated with a single monitor.""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/data/sim_data.py b/tidy3d/components/data/sim_data.py index 8fe12cc92..ff5a8717b 100644 --- a/tidy3d/components/data/sim_data.py +++ b/tidy3d/components/data/sim_data.py @@ -1,4 +1,5 @@ """ Simulation Level Data """ + from __future__ import annotations from typing import Callable, Tuple, Union from abc import ABC diff --git a/tidy3d/components/eme/data/dataset.py b/tidy3d/components/eme/data/dataset.py index 65ffb9fa9..b247b896a 100644 --- a/tidy3d/components/eme/data/dataset.py +++ b/tidy3d/components/eme/data/dataset.py @@ -1,4 +1,5 @@ """EME dataset""" + from __future__ import annotations diff --git a/tidy3d/components/eme/data/monitor_data.py b/tidy3d/components/eme/data/monitor_data.py index 99780af05..92ffadcf8 100644 --- a/tidy3d/components/eme/data/monitor_data.py +++ b/tidy3d/components/eme/data/monitor_data.py @@ -1,4 +1,5 @@ """EME monitor data""" + from __future__ import annotations from typing import Union diff --git a/tidy3d/components/eme/data/sim_data.py b/tidy3d/components/eme/data/sim_data.py index 0b5a22239..f975f59ff 100644 --- a/tidy3d/components/eme/data/sim_data.py +++ b/tidy3d/components/eme/data/sim_data.py @@ -1,4 +1,5 @@ """EME simulation data""" + from __future__ import annotations from typing import Tuple, Union, Optional, Literal diff --git a/tidy3d/components/eme/grid.py b/tidy3d/components/eme/grid.py index bba3571f9..2de5a69ca 100644 --- a/tidy3d/components/eme/grid.py +++ b/tidy3d/components/eme/grid.py @@ -1,4 +1,5 @@ """Defines cells for the EME simulation.""" + from __future__ import annotations from typing import List, Union, Tuple, Literal diff --git a/tidy3d/components/eme/monitor.py b/tidy3d/components/eme/monitor.py index 09d538843..405ec6c49 100644 --- a/tidy3d/components/eme/monitor.py +++ b/tidy3d/components/eme/monitor.py @@ -1,4 +1,5 @@ """EME monitors""" + from __future__ import annotations import pydantic.v1 as pd diff --git a/tidy3d/components/eme/simulation.py b/tidy3d/components/eme/simulation.py index bd3b72ec6..bd83f429b 100644 --- a/tidy3d/components/eme/simulation.py +++ b/tidy3d/components/eme/simulation.py @@ -1,4 +1,5 @@ """Defines EME simulation class.""" + from __future__ import annotations from typing import Tuple, List, Dict, Optional, Literal diff --git a/tidy3d/components/eme/sweep.py b/tidy3d/components/eme/sweep.py index 4cb23d8eb..736cb2b56 100644 --- a/tidy3d/components/eme/sweep.py +++ b/tidy3d/components/eme/sweep.py @@ -1,4 +1,5 @@ """Defines sweep settings for the EME simulation.""" + from __future__ import annotations from typing import List, Union diff --git a/tidy3d/components/field_projection.py b/tidy3d/components/field_projection.py index 6098a22eb..bc0628e04 100644 --- a/tidy3d/components/field_projection.py +++ b/tidy3d/components/field_projection.py @@ -1,5 +1,6 @@ """Near field to far field transformation plugin """ + from __future__ import annotations from typing import Dict, Tuple, Union, List import numpy as np diff --git a/tidy3d/components/geometry/mesh.py b/tidy3d/components/geometry/mesh.py index a4632a569..11d2af7ca 100644 --- a/tidy3d/components/geometry/mesh.py +++ b/tidy3d/components/geometry/mesh.py @@ -1,4 +1,5 @@ """Mesh-defined geometry.""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/geometry/utils.py b/tidy3d/components/geometry/utils.py index 7f8069ec3..d87bc1493 100644 --- a/tidy3d/components/geometry/utils.py +++ b/tidy3d/components/geometry/utils.py @@ -1,4 +1,5 @@ """Utilities for geometry manipulation.""" + from __future__ import annotations from typing import Union, Tuple from math import isclose diff --git a/tidy3d/components/geometry/utils_2d.py b/tidy3d/components/geometry/utils_2d.py index afff6c123..bf68254d2 100644 --- a/tidy3d/components/geometry/utils_2d.py +++ b/tidy3d/components/geometry/utils_2d.py @@ -1,4 +1,5 @@ """Utilities for 2D geometry manipulation.""" + import numpy as np import shapely from typing import Tuple, List diff --git a/tidy3d/components/grid/grid.py b/tidy3d/components/grid/grid.py index b511d71b5..d7d7102af 100644 --- a/tidy3d/components/grid/grid.py +++ b/tidy3d/components/grid/grid.py @@ -1,4 +1,5 @@ """Defines the FDTD grid.""" + from __future__ import annotations from typing import Tuple, List, Union diff --git a/tidy3d/components/grid/grid_spec.py b/tidy3d/components/grid/grid_spec.py index 968e7d9ff..ae905f486 100644 --- a/tidy3d/components/grid/grid_spec.py +++ b/tidy3d/components/grid/grid_spec.py @@ -1,4 +1,5 @@ """ Defines classes specifying meshing in 1D and a collective class for 3D """ + from __future__ import annotations from abc import ABC, abstractmethod @@ -75,7 +76,6 @@ def courant_ratio(self) -> float: class GridSpec1d(Tidy3dBaseModel, ABC): - """Abstract base class, defines 1D grid generation specifications.""" def make_coords( @@ -189,7 +189,6 @@ def _add_pml_to_bounds(num_layers: Tuple[int, int], bounds: Coords1D) -> Coords1 class UniformGrid(GridSpec1d): - """Uniform 1D grid. The most standard way to define a simulation is to use a constant grid size in each of the three directions. Example @@ -252,7 +251,6 @@ def _make_coords_initial( class CustomGrid(GridSpec1d): - """Custom 1D grid supplied as a list of grid cell sizes centered on the simulation center. Example @@ -503,7 +501,6 @@ def _make_coords_initial( class GridSpec(Tidy3dBaseModel): - """Collective grid specification for all three dimensions. Example diff --git a/tidy3d/components/grid/mesher.py b/tidy3d/components/grid/mesher.py index cc7010145..c4756e16c 100644 --- a/tidy3d/components/grid/mesher.py +++ b/tidy3d/components/grid/mesher.py @@ -1121,9 +1121,7 @@ def fun_scale(new_scale): if isclose(new_scale, 1.0): return len_interval - small_dl * (1 + num_step) return ( - len_interval - - small_dl * (1 - new_scale**num_step) / (1 - new_scale) - - small_dl + len_interval - small_dl * (1 - new_scale**num_step) / (1 - new_scale) - small_dl ) # solve for new scaling factor diff --git a/tidy3d/components/heat/boundary.py b/tidy3d/components/heat/boundary.py index 8695fb0d4..beb6de505 100644 --- a/tidy3d/components/heat/boundary.py +++ b/tidy3d/components/heat/boundary.py @@ -1,4 +1,5 @@ """Defines heat material specifications""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/heat/data/monitor_data.py b/tidy3d/components/heat/data/monitor_data.py index 33ec7057f..64014cc02 100644 --- a/tidy3d/components/heat/data/monitor_data.py +++ b/tidy3d/components/heat/data/monitor_data.py @@ -1,4 +1,5 @@ """Monitor level data, store the DataArrays associated with a single heat monitor.""" + from __future__ import annotations from typing import Union, Tuple, Optional diff --git a/tidy3d/components/heat/data/sim_data.py b/tidy3d/components/heat/data/sim_data.py index fde336f94..ca40fbc68 100644 --- a/tidy3d/components/heat/data/sim_data.py +++ b/tidy3d/components/heat/data/sim_data.py @@ -1,4 +1,5 @@ """Defines heat simulation data class""" + from __future__ import annotations from typing import Tuple diff --git a/tidy3d/components/heat/grid.py b/tidy3d/components/heat/grid.py index 57ce44b43..dc5623954 100644 --- a/tidy3d/components/heat/grid.py +++ b/tidy3d/components/heat/grid.py @@ -1,4 +1,5 @@ """Defines heat grid specifications""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/heat/monitor.py b/tidy3d/components/heat/monitor.py index 1fd722a48..4d22ff3da 100644 --- a/tidy3d/components/heat/monitor.py +++ b/tidy3d/components/heat/monitor.py @@ -1,4 +1,5 @@ """Objects that define how data is recorded from simulation.""" + from abc import ABC import pydantic.v1 as pd from typing import Union diff --git a/tidy3d/components/heat/simulation.py b/tidy3d/components/heat/simulation.py index b8e5e7886..ef2d705ba 100644 --- a/tidy3d/components/heat/simulation.py +++ b/tidy3d/components/heat/simulation.py @@ -1,4 +1,5 @@ """Defines heat simulation class""" + from __future__ import annotations from typing import Tuple, List, Dict diff --git a/tidy3d/components/heat/source.py b/tidy3d/components/heat/source.py index db993cdce..e5fa54f4b 100644 --- a/tidy3d/components/heat/source.py +++ b/tidy3d/components/heat/source.py @@ -1,4 +1,5 @@ """Defines heat material specifications""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/heat/viz.py b/tidy3d/components/heat/viz.py index 335a8a9d3..b03acff5d 100644 --- a/tidy3d/components/heat/viz.py +++ b/tidy3d/components/heat/viz.py @@ -1,4 +1,5 @@ """ utilities for heat solver plotting """ + from ..viz import PlotParams """ Constants """ diff --git a/tidy3d/components/heat_spec.py b/tidy3d/components/heat_spec.py index 4666e3227..0aa605dcc 100644 --- a/tidy3d/components/heat_spec.py +++ b/tidy3d/components/heat_spec.py @@ -1,4 +1,5 @@ """Defines heat material specifications""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/components/lumped_element.py b/tidy3d/components/lumped_element.py index 634495d5b..81a19b684 100644 --- a/tidy3d/components/lumped_element.py +++ b/tidy3d/components/lumped_element.py @@ -1,4 +1,5 @@ """Defines lumped elements that should be included in the simulation.""" + from __future__ import annotations from abc import ABC from typing import Union, List, Optional diff --git a/tidy3d/components/medium.py b/tidy3d/components/medium.py index 6194346e9..c85c16840 100644 --- a/tidy3d/components/medium.py +++ b/tidy3d/components/medium.py @@ -1,4 +1,5 @@ """Defines properties of the medium / materials""" + from __future__ import annotations from abc import ABC, abstractmethod @@ -2884,13 +2885,13 @@ class CustomPoleResidue(CustomDispersiveMedium, PoleResidue): units=PERMITTIVITY, ) - poles: Tuple[ - Tuple[CustomSpatialDataTypeAnnotated, CustomSpatialDataTypeAnnotated], ... - ] = pd.Field( - (), - title="Poles", - description="Tuple of complex-valued (:math:`a_i, c_i`) poles for the model.", - units=(RADPERSEC, RADPERSEC), + poles: Tuple[Tuple[CustomSpatialDataTypeAnnotated, CustomSpatialDataTypeAnnotated], ...] = ( + pd.Field( + (), + title="Poles", + description="Tuple of complex-valued (:math:`a_i, c_i`) poles for the model.", + units=(RADPERSEC, RADPERSEC), + ) ) _no_nans_eps_inf = validate_no_nans("eps_inf") @@ -3228,13 +3229,13 @@ class CustomSellmeier(CustomDispersiveMedium, Sellmeier): * `Modeling dispersive material in FDTD `_ """ - coeffs: Tuple[ - Tuple[CustomSpatialDataTypeAnnotated, CustomSpatialDataTypeAnnotated], ... - ] = pd.Field( - ..., - title="Coefficients", - description="List of Sellmeier (:math:`B_i, C_i`) coefficients.", - units=(None, MICROMETER + "^2"), + coeffs: Tuple[Tuple[CustomSpatialDataTypeAnnotated, CustomSpatialDataTypeAnnotated], ...] = ( + pd.Field( + ..., + title="Coefficients", + description="List of Sellmeier (:math:`B_i, C_i`) coefficients.", + units=(None, MICROMETER + "^2"), + ) ) _no_nans = validate_no_nans("coeffs") @@ -3905,13 +3906,13 @@ class CustomDrude(CustomDispersiveMedium, Drude): units=PERMITTIVITY, ) - coeffs: Tuple[ - Tuple[CustomSpatialDataTypeAnnotated, CustomSpatialDataTypeAnnotated], ... - ] = pd.Field( - ..., - title="Coefficients", - description="List of (:math:`f_i, \\delta_i`) values for model.", - units=(HERTZ, HERTZ), + coeffs: Tuple[Tuple[CustomSpatialDataTypeAnnotated, CustomSpatialDataTypeAnnotated], ...] = ( + pd.Field( + ..., + title="Coefficients", + description="List of (:math:`f_i, \\delta_i`) values for model.", + units=(HERTZ, HERTZ), + ) ) _no_nans_eps_inf = validate_no_nans("eps_inf") @@ -4151,13 +4152,13 @@ class CustomDebye(CustomDispersiveMedium, Debye): units=PERMITTIVITY, ) - coeffs: Tuple[ - Tuple[CustomSpatialDataTypeAnnotated, CustomSpatialDataTypeAnnotated], ... - ] = pd.Field( - ..., - title="Coefficients", - description="List of (:math:`\\Delta\\epsilon_i, \\tau_i`) values for model.", - units=(PERMITTIVITY, SECOND), + coeffs: Tuple[Tuple[CustomSpatialDataTypeAnnotated, CustomSpatialDataTypeAnnotated], ...] = ( + pd.Field( + ..., + title="Coefficients", + description="List of (:math:`\\Delta\\epsilon_i, \\tau_i`) values for model.", + units=(PERMITTIVITY, SECOND), + ) ) _no_nans_eps_inf = validate_no_nans("eps_inf") diff --git a/tidy3d/components/monitor.py b/tidy3d/components/monitor.py index 5c95121ae..2196337f4 100644 --- a/tidy3d/components/monitor.py +++ b/tidy3d/components/monitor.py @@ -1,4 +1,5 @@ """Objects that define how data is recorded from simulation.""" + from abc import ABC, abstractmethod from typing import Union, Tuple @@ -216,14 +217,14 @@ class AbstractFieldMonitor(Monitor, ABC): description="Collection of field components to store in the monitor.", ) - interval_space: Tuple[ - pydantic.PositiveInt, pydantic.PositiveInt, pydantic.PositiveInt - ] = pydantic.Field( - (1, 1, 1), - title="Spatial Interval", - description="Number of grid step intervals between monitor recordings. If equal to 1, " - "there will be no downsampling. If greater than 1, the step will be applied, but the " - "first and last point of the monitor grid are always included.", + interval_space: Tuple[pydantic.PositiveInt, pydantic.PositiveInt, pydantic.PositiveInt] = ( + pydantic.Field( + (1, 1, 1), + title="Spatial Interval", + description="Number of grid step intervals between monitor recordings. If equal to 1, " + "there will be no downsampling. If greater than 1, the step will be applied, but the " + "first and last point of the monitor grid are always included.", + ) ) colocate: bool = pydantic.Field( @@ -461,14 +462,14 @@ class PermittivityMonitor(FreqMonitor): "physical meaning - they do not correspond to the subpixel-averaged ones.", ) - interval_space: Tuple[ - pydantic.PositiveInt, pydantic.PositiveInt, pydantic.PositiveInt - ] = pydantic.Field( - (1, 1, 1), - title="Spatial Interval", - description="Number of grid step intervals between monitor recordings. If equal to 1, " - "there will be no downsampling. If greater than 1, the step will be applied, but the " - "first and last point of the monitor grid are always included.", + interval_space: Tuple[pydantic.PositiveInt, pydantic.PositiveInt, pydantic.PositiveInt] = ( + pydantic.Field( + (1, 1, 1), + title="Spatial Interval", + description="Number of grid step intervals between monitor recordings. If equal to 1, " + "there will be no downsampling. If greater than 1, the step will be applied, but the " + "first and last point of the monitor grid are always included.", + ) ) apodization: ApodizationSpec = pydantic.Field( @@ -788,19 +789,19 @@ class AbstractFieldProjectionMonitor(SurfaceIntegrationMonitor, FreqMonitor): "in the far field of the device.", ) - interval_space: Tuple[ - pydantic.PositiveInt, pydantic.PositiveInt, pydantic.PositiveInt - ] = pydantic.Field( - (1, 1, 1), - title="Spatial Interval", - description="Number of grid step intervals at which near fields are recorded for " - "projection to the far field, along each direction. If equal to 1, there will be no " - "downsampling. If greater than 1, the step will be applied, but the first and last " - "point of the monitor grid are always included. Using values greater than 1 can " - "help speed up server-side far field projections with minimal accuracy loss, " - "especially in cases where it is necessary for the grid resolution to be high for " - "the FDTD simulation, but such a high resolution is unnecessary for the purpose of " - "projecting the recorded near fields to the far field.", + interval_space: Tuple[pydantic.PositiveInt, pydantic.PositiveInt, pydantic.PositiveInt] = ( + pydantic.Field( + (1, 1, 1), + title="Spatial Interval", + description="Number of grid step intervals at which near fields are recorded for " + "projection to the far field, along each direction. If equal to 1, there will be no " + "downsampling. If greater than 1, the step will be applied, but the first and last " + "point of the monitor grid are always included. Using values greater than 1 can " + "help speed up server-side far field projections with minimal accuracy loss, " + "especially in cases where it is necessary for the grid resolution to be high for " + "the FDTD simulation, but such a high resolution is unnecessary for the purpose of " + "projecting the recorded near fields to the far field.", + ) ) window_size: Tuple[pydantic.NonNegativeFloat, pydantic.NonNegativeFloat] = pydantic.Field( diff --git a/tidy3d/components/parameter_perturbation.py b/tidy3d/components/parameter_perturbation.py index 06a1bf053..ca4260f74 100644 --- a/tidy3d/components/parameter_perturbation.py +++ b/tidy3d/components/parameter_perturbation.py @@ -1,4 +1,5 @@ """Defines perturbations to properties of the medium / materials""" + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/components/scene.py b/tidy3d/components/scene.py index 94a3f1ab4..936f93d95 100644 --- a/tidy3d/components/scene.py +++ b/tidy3d/components/scene.py @@ -1,5 +1,6 @@ """ Container holding about the geometry and medium properties common to all types of simulations. """ + from __future__ import annotations from typing import Dict, Tuple, List, Set, Union diff --git a/tidy3d/components/simulation.py b/tidy3d/components/simulation.py index bc8cbf84b..083df4461 100644 --- a/tidy3d/components/simulation.py +++ b/tidy3d/components/simulation.py @@ -1,4 +1,5 @@ """ Container holding all information about simulation and its components""" + from __future__ import annotations from typing import Dict, Tuple, List, Set, Union diff --git a/tidy3d/components/source.py b/tidy3d/components/source.py index ed3748b1d..b161493fa 100644 --- a/tidy3d/components/source.py +++ b/tidy3d/components/source.py @@ -1,6 +1,5 @@ """Defines electric current sources for injecting light into simulation.""" - from __future__ import annotations from abc import ABC, abstractmethod from typing import Union, Tuple, Optional diff --git a/tidy3d/components/structure.py b/tidy3d/components/structure.py index df3830502..045212cb3 100644 --- a/tidy3d/components/structure.py +++ b/tidy3d/components/structure.py @@ -1,4 +1,5 @@ """Defines Geometric objects with Medium properties.""" + from __future__ import annotations from typing import Union, Tuple, Optional diff --git a/tidy3d/components/time.py b/tidy3d/components/time.py index 1117ec6dd..baad0e8c0 100644 --- a/tidy3d/components/time.py +++ b/tidy3d/components/time.py @@ -1,4 +1,5 @@ """ Defines time dependence """ + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/components/time_modulation.py b/tidy3d/components/time_modulation.py index 0961f36aa..dc41d07c4 100644 --- a/tidy3d/components/time_modulation.py +++ b/tidy3d/components/time_modulation.py @@ -1,4 +1,5 @@ """ Defines time modulation to the medium""" + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/components/transformation.py b/tidy3d/components/transformation.py index 012ade3e2..01c7af151 100644 --- a/tidy3d/components/transformation.py +++ b/tidy3d/components/transformation.py @@ -1,4 +1,5 @@ """Defines geometric transformation classes""" + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/components/viz.py b/tidy3d/components/viz.py index f8791d90e..145125522 100644 --- a/tidy3d/components/viz.py +++ b/tidy3d/components/viz.py @@ -1,4 +1,5 @@ """ utilities for plotting """ + from __future__ import annotations from typing import Any diff --git a/tidy3d/material_library/material_library.py b/tidy3d/material_library/material_library.py index 812ced392..5a7e616d8 100644 --- a/tidy3d/material_library/material_library.py +++ b/tidy3d/material_library/material_library.py @@ -1,4 +1,5 @@ """Holds dispersive models for several commonly used optical materials.""" + import json from typing import Dict, List import pydantic.v1 as pd diff --git a/tidy3d/material_library/material_reference.py b/tidy3d/material_library/material_reference.py index 2616e05cc..ac272e541 100644 --- a/tidy3d/material_library/material_reference.py +++ b/tidy3d/material_library/material_reference.py @@ -1,4 +1,5 @@ """Holds the reference materials for Tidy3D material library.""" + import pydantic.v1 as pd from ..components.base import Tidy3dBaseModel diff --git a/tidy3d/material_library/parametric_materials.py b/tidy3d/material_library/parametric_materials.py index 70206d103..1333fee72 100644 --- a/tidy3d/material_library/parametric_materials.py +++ b/tidy3d/material_library/parametric_materials.py @@ -1,4 +1,5 @@ """Parametric material models.""" + from abc import ABC, abstractmethod from typing import List, Tuple import warnings diff --git a/tidy3d/packaging.py b/tidy3d/packaging.py index fceecc111..f404af25d 100644 --- a/tidy3d/packaging.py +++ b/tidy3d/packaging.py @@ -3,6 +3,7 @@ This section should only depend on the standard core installation in the pyproject.toml, and should not depend on any other part of the codebase optional imports. """ + import functools import numpy as np from typing import Literal diff --git a/tidy3d/plugins/adjoint/components/base.py b/tidy3d/plugins/adjoint/components/base.py index 3b1e515e5..cb5221a96 100644 --- a/tidy3d/plugins/adjoint/components/base.py +++ b/tidy3d/plugins/adjoint/components/base.py @@ -1,4 +1,5 @@ """Base model for Tidy3D components that are compatible with jax.""" + from __future__ import annotations from typing import Tuple, List, Any, Callable diff --git a/tidy3d/plugins/adjoint/components/data/data_array.py b/tidy3d/plugins/adjoint/components/data/data_array.py index b10e6ab03..465d07499 100644 --- a/tidy3d/plugins/adjoint/components/data/data_array.py +++ b/tidy3d/plugins/adjoint/components/data/data_array.py @@ -1,4 +1,5 @@ """Defines jax-compatible DataArrays.""" + from __future__ import annotations from typing import Tuple, Any, Dict, List diff --git a/tidy3d/plugins/adjoint/components/data/dataset.py b/tidy3d/plugins/adjoint/components/data/dataset.py index c9c72590b..12602175c 100644 --- a/tidy3d/plugins/adjoint/components/data/dataset.py +++ b/tidy3d/plugins/adjoint/components/data/dataset.py @@ -1,4 +1,5 @@ """Defines jax-compatible datasets.""" + import pydantic.v1 as pd from jax.tree_util import register_pytree_node_class diff --git a/tidy3d/plugins/adjoint/components/data/monitor_data.py b/tidy3d/plugins/adjoint/components/data/monitor_data.py index 73fc09a3c..e69d821fb 100644 --- a/tidy3d/plugins/adjoint/components/data/monitor_data.py +++ b/tidy3d/plugins/adjoint/components/data/monitor_data.py @@ -1,4 +1,5 @@ """Defines jax-compatible MonitorData and their conversion to adjoint sources.""" + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/plugins/adjoint/components/data/sim_data.py b/tidy3d/plugins/adjoint/components/data/sim_data.py index e74197bdb..8806a118f 100644 --- a/tidy3d/plugins/adjoint/components/data/sim_data.py +++ b/tidy3d/plugins/adjoint/components/data/sim_data.py @@ -1,4 +1,5 @@ """Defines a jax-compatible SimulationData.""" + from __future__ import annotations from typing import Tuple, Dict, Union, List diff --git a/tidy3d/plugins/adjoint/components/geometry.py b/tidy3d/plugins/adjoint/components/geometry.py index 2de86ffe4..2bbe9cfea 100644 --- a/tidy3d/plugins/adjoint/components/geometry.py +++ b/tidy3d/plugins/adjoint/components/geometry.py @@ -1,4 +1,5 @@ """Defines jax-compatible geometries and their conversion to grad monitors.""" + from __future__ import annotations from abc import ABC diff --git a/tidy3d/plugins/adjoint/components/medium.py b/tidy3d/plugins/adjoint/components/medium.py index ad1790058..4143ad589 100644 --- a/tidy3d/plugins/adjoint/components/medium.py +++ b/tidy3d/plugins/adjoint/components/medium.py @@ -1,4 +1,5 @@ """Defines jax-compatible mediums.""" + from __future__ import annotations from typing import Dict, Tuple, Union, Callable, Optional diff --git a/tidy3d/plugins/adjoint/components/simulation.py b/tidy3d/plugins/adjoint/components/simulation.py index 8e82feda9..c2f125601 100644 --- a/tidy3d/plugins/adjoint/components/simulation.py +++ b/tidy3d/plugins/adjoint/components/simulation.py @@ -1,4 +1,5 @@ """Defines a jax-compatible simulation.""" + from __future__ import annotations from typing import Tuple, Union, List, Dict, Literal diff --git a/tidy3d/plugins/adjoint/components/structure.py b/tidy3d/plugins/adjoint/components/structure.py index 4e5785ddf..c4706acc6 100644 --- a/tidy3d/plugins/adjoint/components/structure.py +++ b/tidy3d/plugins/adjoint/components/structure.py @@ -1,4 +1,5 @@ """Defines a jax-compatible structure and its conversion to a gradient monitor.""" + from __future__ import annotations from typing import List, Union, Dict diff --git a/tidy3d/plugins/adjoint/components/types.py b/tidy3d/plugins/adjoint/components/types.py index 3224d3dbf..f4c14b561 100644 --- a/tidy3d/plugins/adjoint/components/types.py +++ b/tidy3d/plugins/adjoint/components/types.py @@ -1,4 +1,5 @@ """Special types and validators used by adjoint plugin.""" + from typing import Union, Any import numpy as np diff --git a/tidy3d/plugins/adjoint/utils/filter.py b/tidy3d/plugins/adjoint/utils/filter.py index 98017a0a9..c92c7b0c8 100644 --- a/tidy3d/plugins/adjoint/utils/filter.py +++ b/tidy3d/plugins/adjoint/utils/filter.py @@ -1,4 +1,5 @@ """Spatial filtering Functions for adjoint plugin.""" + from abc import ABC, abstractmethod import pydantic.v1 as pd diff --git a/tidy3d/plugins/adjoint/utils/penalty.py b/tidy3d/plugins/adjoint/utils/penalty.py index ec4ca7457..1f927bcdc 100644 --- a/tidy3d/plugins/adjoint/utils/penalty.py +++ b/tidy3d/plugins/adjoint/utils/penalty.py @@ -1,4 +1,5 @@ """Penalty Functions for adjoint plugin.""" + from abc import ABC, abstractmethod import pydantic.v1 as pd diff --git a/tidy3d/plugins/adjoint/web.py b/tidy3d/plugins/adjoint/web.py index 43a9c51b6..9cf707353 100644 --- a/tidy3d/plugins/adjoint/web.py +++ b/tidy3d/plugins/adjoint/web.py @@ -1,4 +1,5 @@ """Adjoint-specific webapi.""" + from typing import Tuple, Dict, List from functools import partial import tempfile diff --git a/tidy3d/plugins/design/__init__.py b/tidy3d/plugins/design/__init__.py index 369fe58ab..83ea56104 100644 --- a/tidy3d/plugins/design/__init__.py +++ b/tidy3d/plugins/design/__init__.py @@ -1,4 +1,5 @@ """Imports for parameter sweep.""" + from .parameter import ParameterAny, ParameterFloat, ParameterInt from .design import DesignSpace from .method import MethodMonteCarlo, MethodGrid, MethodRandom, MethodRandomCustom diff --git a/tidy3d/plugins/design/design.py b/tidy3d/plugins/design/design.py index 22ca62db7..547c1aca1 100644 --- a/tidy3d/plugins/design/design.py +++ b/tidy3d/plugins/design/design.py @@ -1,4 +1,5 @@ """Defines design space specification for tidy3d.""" + from __future__ import annotations from typing import Tuple, Callable, Dict, Any, List, Union diff --git a/tidy3d/plugins/design/method.py b/tidy3d/plugins/design/method.py index 4c72e8dcb..b68cabee5 100644 --- a/tidy3d/plugins/design/method.py +++ b/tidy3d/plugins/design/method.py @@ -1,4 +1,5 @@ """Defines the methods used for parameter sweep.""" + from typing import Union, Tuple, Dict, Any, Callable from abc import ABC, abstractmethod diff --git a/tidy3d/plugins/design/parameter.py b/tidy3d/plugins/design/parameter.py index c10291983..768b58728 100644 --- a/tidy3d/plugins/design/parameter.py +++ b/tidy3d/plugins/design/parameter.py @@ -1,4 +1,5 @@ """Defines the dimensions of the parameter sweep and their properties.""" + from __future__ import annotations from typing import Tuple, Any, Union, List diff --git a/tidy3d/plugins/design/result.py b/tidy3d/plugins/design/result.py index 40b69e485..37983e94b 100644 --- a/tidy3d/plugins/design/result.py +++ b/tidy3d/plugins/design/result.py @@ -1,4 +1,5 @@ """Defines parameter sweeping utilities for tidy3d.""" + from __future__ import annotations from typing import Tuple, Dict, Any, List diff --git a/tidy3d/plugins/dispersion/fit_web.py b/tidy3d/plugins/dispersion/fit_web.py index 247d5ac40..4eac61073 100644 --- a/tidy3d/plugins/dispersion/fit_web.py +++ b/tidy3d/plugins/dispersion/fit_web.py @@ -1,4 +1,5 @@ """Deprecated module""" + from ...log import log log.warning( diff --git a/tidy3d/plugins/microwave/models/coupled_microstrip.py b/tidy3d/plugins/microwave/models/coupled_microstrip.py index 8ce0e3a81..6a72d3870 100644 --- a/tidy3d/plugins/microwave/models/coupled_microstrip.py +++ b/tidy3d/plugins/microwave/models/coupled_microstrip.py @@ -63,11 +63,7 @@ def _z0_even_odd( Q3 = 0.1975 + (16.6 + (8.4 / g) ** 6) ** -0.387 + np.log(g**10 / (1 + (g / 3.4) ** 10)) / 241 Q4 = (2 * Q1 / Q2) * (np.exp(-g) * u**Q3 + (2 - np.exp(-g)) * u**-Q3) ** -1 Q5 = 1.794 + 1.14 * np.log(1 + 0.638 / (g + 0.517 * g**2.43)) - Q6 = ( - 0.2305 - + np.log(g**10 / (1 + (g / 5.8) ** 10)) / 281.3 - + np.log(1 + 0.598 * g**1.154) / 5.1 - ) + Q6 = 0.2305 + np.log(g**10 / (1 + (g / 5.8) ** 10)) / 281.3 + np.log(1 + 0.598 * g**1.154) / 5.1 Q7 = (10 + 190 * g**2) / (1 + 82.3 * g**3) Q8 = np.exp(-6.5 - 0.95 * np.log(g) - (g / 0.15) ** 5) Q9 = np.log(Q7) * (Q8 + 1 / 16.5) diff --git a/tidy3d/plugins/mode/mode_solver.py b/tidy3d/plugins/mode/mode_solver.py index 34674aa23..0f2e917e8 100644 --- a/tidy3d/plugins/mode/mode_solver.py +++ b/tidy3d/plugins/mode/mode_solver.py @@ -52,6 +52,10 @@ # Maximum allowed size of the field data produced by the mode solver MAX_MODES_DATA_SIZE_GB = 20 +# Default number of jobs (or workers) settings for parallel computing in joblib.Parallel +# For numbers below -1, (n_cpus+1+n_jobs) are used +DEFAULT_NUM_JOB: int = -2 + class ModeSolver(Tidy3dBaseModel): """ diff --git a/tidy3d/plugins/mode/solver.py b/tidy3d/plugins/mode/solver.py index 423c49b50..96d552eb7 100644 --- a/tidy3d/plugins/mode/solver.py +++ b/tidy3d/plugins/mode/solver.py @@ -1,4 +1,5 @@ """Mode solver for propagating EM modes.""" + from typing import Tuple import numpy as np diff --git a/tidy3d/plugins/mode/web.py b/tidy3d/plugins/mode/web.py index cc132832c..edbbbecca 100644 --- a/tidy3d/plugins/mode/web.py +++ b/tidy3d/plugins/mode/web.py @@ -1,4 +1,5 @@ """Web API for mode solver""" -from ...web.api.mode import run -__all__ = ["run"] +from ...web.api.mode import run, run_batch + +__all__ = ["run", "run_batch"] diff --git a/tidy3d/plugins/smatrix/component_modelers/base.py b/tidy3d/plugins/smatrix/component_modelers/base.py index 555ef39c0..fd4bc7f3b 100644 --- a/tidy3d/plugins/smatrix/component_modelers/base.py +++ b/tidy3d/plugins/smatrix/component_modelers/base.py @@ -1,4 +1,5 @@ """Base class for generating an S matrix automatically from tidy3d simulations and port definitions.""" + from __future__ import annotations from typing import Tuple, Dict, Union import os diff --git a/tidy3d/plugins/smatrix/component_modelers/modal.py b/tidy3d/plugins/smatrix/component_modelers/modal.py index f77196241..b5f23bc7d 100644 --- a/tidy3d/plugins/smatrix/component_modelers/modal.py +++ b/tidy3d/plugins/smatrix/component_modelers/modal.py @@ -1,4 +1,5 @@ """Tool for generating an S matrix automatically from a Tidy3d simulation and modal port definitions.""" + # TODO: The names "ComponentModeler" and "Port" should be changed to "ModalComponentModeler" and # "ModalPort" to explicitly differentiate these from "TerminalComponentModeler" and "LumpedPort". from __future__ import annotations diff --git a/tidy3d/plugins/smatrix/ports/modal.py b/tidy3d/plugins/smatrix/ports/modal.py index 1e51427ea..bf63ca3c2 100644 --- a/tidy3d/plugins/smatrix/ports/modal.py +++ b/tidy3d/plugins/smatrix/ports/modal.py @@ -1,4 +1,5 @@ """Class and custom data array for representing a scattering matrix port based on waveguide modes.""" + import pydantic.v1 as pd from ....components.geometry.base import Box diff --git a/tidy3d/updater.py b/tidy3d/updater.py index 6e07eeb7c..b45cc59e1 100644 --- a/tidy3d/updater.py +++ b/tidy3d/updater.py @@ -1,4 +1,5 @@ """Utilities for converting between tidy3d versions.""" + from __future__ import annotations from typing import Dict, Callable diff --git a/tidy3d/version.py b/tidy3d/version.py index ff2b2e02a..7ba8e0778 100644 --- a/tidy3d/version.py +++ b/tidy3d/version.py @@ -1,2 +1,3 @@ """DO NOT EDIT: Modified automatically with .bump2version.cfg""" + __version__ = "2.7.0rc2" diff --git a/tidy3d/web/__init__.py b/tidy3d/web/__init__.py index 0e6b90bde..2ac0bb604 100644 --- a/tidy3d/web/__init__.py +++ b/tidy3d/web/__init__.py @@ -1,4 +1,5 @@ """ imports interfaces for interacting with server """ + from .core import core_config from ..log import log, get_logging_console from ..version import __version__ diff --git a/tidy3d/web/api/asynchronous.py b/tidy3d/web/api/asynchronous.py index ffa84c860..a78927470 100644 --- a/tidy3d/web/api/asynchronous.py +++ b/tidy3d/web/api/asynchronous.py @@ -1,4 +1,5 @@ """Interface to run several jobs in batch using simplified syntax.""" + from typing import Dict, List from .container import DEFAULT_DATA_DIR, BatchData, Batch diff --git a/tidy3d/web/api/container.py b/tidy3d/web/api/container.py index 72ab4ce23..ad90231e5 100644 --- a/tidy3d/web/api/container.py +++ b/tidy3d/web/api/container.py @@ -1,4 +1,5 @@ """higher level wrappers for webapi functions for individual (Job) and batch (Batch) tasks.""" + from __future__ import annotations import os diff --git a/tidy3d/web/api/material_fitter.py b/tidy3d/web/api/material_fitter.py index d9670543a..3f429879a 100644 --- a/tidy3d/web/api/material_fitter.py +++ b/tidy3d/web/api/material_fitter.py @@ -1,4 +1,5 @@ """Material Fitter API.""" + from __future__ import annotations import os diff --git a/tidy3d/web/api/mode.py b/tidy3d/web/api/mode.py index aa90e706d..dd6b7c7cf 100644 --- a/tidy3d/web/api/mode.py +++ b/tidy3d/web/api/mode.py @@ -12,6 +12,10 @@ import pydantic.v1 as pydantic from botocore.exceptions import ClientError +from typing import List +from concurrent.futures import ThreadPoolExecutor, as_completed +from rich.progress import Progress + from ..core.environment import Env from ...components.simulation import Simulation from ...components.data.monitor_data import ModeSolverData @@ -39,6 +43,10 @@ MODESOLVER_RESULT = "output/result.hdf5" MODESOLVER_RESULT_GZ = "output/mode_solver_data.hdf5.gz" +DEFAULT_NUM_WORKERS = 10 +DEFAULT_MAX_RETRIES = 3 +DEFAULT_RETRY_DELAY = 10 # in seconds + def run( mode_solver: ModeSolver, @@ -138,6 +146,111 @@ def run( ) +def run_batch( + mode_solvers: List[ModeSolver], + task_name: str = "BatchModeSolver", + folder_name: str = "BatchModeSolvers", + results_files: List[str] = None, + verbose: bool = True, + max_workers: int = DEFAULT_NUM_WORKERS, + max_retries: int = DEFAULT_MAX_RETRIES, + retry_delay: float = DEFAULT_RETRY_DELAY, + progress_callback_upload: Callable[[float], None] = None, + progress_callback_download: Callable[[float], None] = None, +) -> List[ModeSolverData]: + """ + Submits a batch of ModeSolver to the server concurrently, manages progress, and retrieves results. + + Parameters + ---------- + mode_solvers : List[ModeSolver] + List of mode solvers to be submitted to the server. + task_name : str + Base name for tasks. Each task in the batch will have a unique index appended to this base name. + folder_name : str + Name of the folder where tasks are stored on the server's web UI. + results_files : List[str], optional + List of file paths where the results for each ModeSolver should be downloaded. If None, a default path based on the folder name and index is used. + verbose : bool + If True, displays a progress bar. If False, runs silently. + max_workers : int + Maximum number of concurrent workers to use for processing the batch of simulations. + max_retries : int + Maximum number of retries for each simulation in case of failure before giving up. + retry_delay : int + Delay in seconds between retries when a simulation fails. + progress_callback_upload : Callable[[float], None], optional + Optional callback function called when uploading file with ``bytes_in_chunk`` as argument. + progress_callback_download : Callable[[float], None], optional + Optional callback function called when downloading file with ``bytes_in_chunk`` as argument. + + + Returns + ------- + List[ModeSolverData] + A list of ModeSolverData objects containing the results from each simulation in the batch. ``None`` is placed in the list for simulations that fail after all retries. + """ + console = get_logging_console() + + # Check type to make sure the user is submitting a list of mode solvers + if not all(isinstance(x, ModeSolver) for x in mode_solvers): + raise ValueError( + "`modes_solvers` passed to `tidy3d.plugins.mode.web.run_batch()` should be a list containing all `ModeSolver` instances. Cannot run the batched mode solver." + ) + + num_mode_solvers = len(mode_solvers) + + # Result files where the data is stored after downloading + if results_files is None: + results_files = [ + f"{folder_name}/mode_solver_results_{i}.hdf5" for i in range(num_mode_solvers) + ] + + results = [None] * num_mode_solvers + + # Handling simulation to make sure there are more than one tries if simulation produces some error + def handle_mode_solver(index, retries=0): + try: + # We'll create a separate progress bar for batch simulations so we'll set verbose=False here for individual runs + result = run( + mode_solver=mode_solvers[index], + task_name=f"{task_name}_{index}", + mode_solver_name=f"mode_solver_batch_{index}", + folder_name=folder_name, + results_file=results_files[index], + verbose=False, + progress_callback_upload=progress_callback_upload, + progress_callback_download=progress_callback_download, + ) + results[index] = result + except Exception: + if retries < max_retries: + # Wait before retrying + time.sleep(retry_delay) + handle_mode_solver(index, retries + 1) + else: + log.warning(f"The {index}-th mode solver failed after {max_retries} tries.") + log.warning(f"The data returned for the {index}-th mode solver will be `None`.") + + # Using multithreading to run mode solver simulations concurrently + with ThreadPoolExecutor(max_workers=max_workers) as executor: + futures = [executor.submit(handle_mode_solver, i) for i in range(num_mode_solvers)] + # Creating a progress bar for batch simulations using rich progress + if verbose: + console.log(f"[cyan]Running a batch of [deep_pink4]{num_mode_solvers} mode solvers.\n") + with Progress(console=console) as progress: + pbar_message = "Status:" + pbar = progress.add_task(pbar_message, total=num_mode_solvers) + for _ in as_completed(futures): + progress.advance(pbar) + + # Make sure the progress bar is complete + progress.update(pbar, completed=num_mode_solvers, refresh=True) + console.log("[green]A batch of `ModeSolver` tasks completed successfully!") + + return results + + class ModeSolverTask(ResourceLifecycle, Submittable, extra=pydantic.Extra.allow): """Interface for managing the running of a :class:`.ModeSolver` task on server.""" diff --git a/tidy3d/web/api/tidy3d_stub.py b/tidy3d/web/api/tidy3d_stub.py index 24cc25d53..c262df395 100644 --- a/tidy3d/web/api/tidy3d_stub.py +++ b/tidy3d/web/api/tidy3d_stub.py @@ -1,4 +1,5 @@ """Stub for webapi""" + from __future__ import annotations import json diff --git a/tidy3d/web/cli/__init__.py b/tidy3d/web/cli/__init__.py index 7fcaf0bb2..ada31566b 100644 --- a/tidy3d/web/cli/__init__.py +++ b/tidy3d/web/cli/__init__.py @@ -1,6 +1,7 @@ """ tidy3d command line tool. """ + from .app import tidy3d_cli __all__ = ["tidy3d_cli"] diff --git a/tidy3d/web/cli/app.py b/tidy3d/web/cli/app.py index 7f9af893a..26f4a34a4 100644 --- a/tidy3d/web/cli/app.py +++ b/tidy3d/web/cli/app.py @@ -1,6 +1,7 @@ """ Commandline interface for tidy3d. """ + import json import os.path import ssl diff --git a/tidy3d/web/cli/develop/documentation.py b/tidy3d/web/cli/develop/documentation.py index 2d4938364..a75594bf3 100644 --- a/tidy3d/web/cli/develop/documentation.py +++ b/tidy3d/web/cli/develop/documentation.py @@ -12,6 +12,7 @@ poetry run tidy3d develop convert-all-markdown-to-rst """ + import click import json import os diff --git a/tidy3d/web/cli/develop/index.py b/tidy3d/web/cli/develop/index.py index d6edefec6..ac0af5f32 100644 --- a/tidy3d/web/cli/develop/index.py +++ b/tidy3d/web/cli/develop/index.py @@ -1,4 +1,5 @@ """Console script subcommand for tidy3d.""" + import click __all__ = [ diff --git a/tidy3d/web/cli/migrate.py b/tidy3d/web/cli/migrate.py index 9b31c071a..ce5ed6d6e 100644 --- a/tidy3d/web/cli/migrate.py +++ b/tidy3d/web/cli/migrate.py @@ -1,4 +1,5 @@ """Migrate authentication to API key.""" + import json import os diff --git a/tidy3d/web/core/environment.py b/tidy3d/web/core/environment.py index e5797ce83..23a4d0866 100644 --- a/tidy3d/web/core/environment.py +++ b/tidy3d/web/core/environment.py @@ -1,4 +1,5 @@ """Environment Setup.""" + import os from .core_config import get_logger diff --git a/tidy3d/web/core/exceptions.py b/tidy3d/web/core/exceptions.py index 873adebe9..6eefaec4a 100644 --- a/tidy3d/web/core/exceptions.py +++ b/tidy3d/web/core/exceptions.py @@ -1,4 +1,5 @@ """Custom Tidy3D exceptions""" + from .core_config import get_logger diff --git a/tidy3d/web/core/s3utils.py b/tidy3d/web/core/s3utils.py index 5d629ce2e..df9855b49 100644 --- a/tidy3d/web/core/s3utils.py +++ b/tidy3d/web/core/s3utils.py @@ -1,5 +1,6 @@ """handles filesystem, storage """ + import os import tempfile @@ -251,9 +252,9 @@ def _upload(_callback: Callable) -> None: Key=token.get_s3_key(), Callback=_callback, Config=_s3_config, - ExtraArgs={"ContentEncoding": "gzip"} - if token.get_s3_key().endswith(".gz") - else None, + ExtraArgs=( + {"ContentEncoding": "gzip"} if token.get_s3_key().endswith(".gz") else None + ), ) if progress_callback is not None: diff --git a/tidy3d/web/core/stub.py b/tidy3d/web/core/stub.py index 2f9d920b3..9b4c5fd4a 100644 --- a/tidy3d/web/core/stub.py +++ b/tidy3d/web/core/stub.py @@ -1,4 +1,5 @@ """Defines interface that can be subclassed to use with the tidy3d webapi""" + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/web/core/task_core.py b/tidy3d/web/core/task_core.py index a1541c2d7..6a8a04472 100644 --- a/tidy3d/web/core/task_core.py +++ b/tidy3d/web/core/task_core.py @@ -1,4 +1,5 @@ """Tidy3d webapi types.""" + from __future__ import annotations import os diff --git a/tidy3d/web/core/task_info.py b/tidy3d/web/core/task_info.py index f1714db3a..f77257b39 100644 --- a/tidy3d/web/core/task_info.py +++ b/tidy3d/web/core/task_info.py @@ -1,4 +1,5 @@ """ Defnes information about a task """ + from datetime import datetime from enum import Enum from abc import ABC diff --git a/tidy3d/web/core/types.py b/tidy3d/web/core/types.py index 1615775d9..e7a81904a 100644 --- a/tidy3d/web/core/types.py +++ b/tidy3d/web/core/types.py @@ -1,4 +1,5 @@ """Tidy3d abstraction types for the core.""" + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/tidy3d/web/environment.py b/tidy3d/web/environment.py index a1643b093..74b52b8c6 100644 --- a/tidy3d/web/environment.py +++ b/tidy3d/web/environment.py @@ -1,4 +1,5 @@ """ preserve from tidy3d.web.environment import Env backward compatibility """ + from .core.environment import Env __all__ = ["Env"]