Skip to content

Commit

Permalink
adding support for coaxial lumped ports and elements
Browse files Browse the repository at this point in the history
extending impedance calculator for custom paths and fixing one bug

modified convention for vertices in custom path integral
  • Loading branch information
dmarek-flex committed May 24, 2024
1 parent b3d2f82 commit 1e48527
Show file tree
Hide file tree
Showing 27 changed files with 1,649 additions and 429 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for complex and self-intersecting polyslabs in adjoint module via `JaxComplexPolySlab`.
- Support for `.gz` files in `Simulation` version updater.
- Warning if a nonuniform custom medium is intersecting `PlaneWave`, `GaussianBeam`, `AstigmaticGaussianBeam`, `FieldProjectionCartesianMonitor`, `FieldProjectionAngleMonitor`, `FieldProjectionKSpaceMonitor`, and `DiffractionMonitor`.
- Added a `CoaxialLumpedPort` and `CoaxialLumpedResistor` for coaxial type transmission lines and excitations.

### Changed
- `tidy3d convert` from `.lsf` files to tidy3d scripts has moved to another repository at `https://github.com/hirako22/Lumerical-to-Tidy3D-Converter`.
Expand Down
1 change: 1 addition & 0 deletions docs/api/lumped_elements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ Passive elements
:template: module.rst

tidy3d.LumpedResistor
tidy3d.CoaxialLumpedResistor
3 changes: 3 additions & 0 deletions docs/api/plugins/microwave.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ Microwave
tidy3d.plugins.microwave.AxisAlignedPathIntegral
tidy3d.plugins.microwave.VoltageIntegralAxisAligned
tidy3d.plugins.microwave.CurrentIntegralAxisAligned
tidy3d.plugins.microwave.CustomPathIntegral2D
tidy3d.plugins.microwave.CustomVoltageIntegral2D
tidy3d.plugins.microwave.CustomCurrentIntegral2D
tidy3d.plugins.microwave.ImpedanceCalculator
3 changes: 2 additions & 1 deletion docs/api/plugins/smatrix.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ Scattering Matrix Calculator
tidy3d.plugins.smatrix.ModalPortDataArray
tidy3d.plugins.smatrix.TerminalComponentModeler
tidy3d.plugins.smatrix.LumpedPort
tidy3d.plugins.smatrix.LumpedPortDataArray
tidy3d.plugins.smatrix.LumpedPortDataArray
tidy3d.plugins.smatrix.CoaxialLumpedPort
50 changes: 49 additions & 1 deletion tests/test_components/test_medium.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,10 +754,16 @@ def test_lumped_resistor():
voltage_axis=0,
name="R",
)
_ = resistor.sheet_conductance
_ = resistor._sheet_conductance
normal_axis = resistor.normal_axis
assert normal_axis == 1

# Check conversion to geometry
_ = resistor.to_structure

# Check conversion to mesh overrides
_ = resistor.to_mesh_overrides()

# error if voltage axis is not in plane with the resistor
with pytest.raises(pydantic.ValidationError):
_ = td.LumpedResistor(
Expand Down Expand Up @@ -785,3 +791,45 @@ def test_lumped_resistor():
voltage_axis=2,
name="R",
)


def test_coaxial_lumped_resistor():
resistor = td.CoaxialLumpedResistor(
resistance=50.0,
center=[0, 0, 0],
outer_diameter=3,
inner_diameter=1,
normal_axis=1,
name="R",
)

_ = resistor._sheet_conductance
normal_axis = resistor.normal_axis
assert normal_axis == 1

# Check conversion to geometry
_ = resistor.to_structure

# Check conversion to mesh overrides
_ = resistor.to_mesh_overrides()

# error if inner diameter is larger
with pytest.raises(pydantic.ValidationError):
_ = td.CoaxialLumpedResistor(
resistance=50.0,
center=[0, 0, 0],
outer_diameter=3,
inner_diameter=4,
normal_axis=1,
name="R",
)

with pytest.raises(pydantic.ValidationError):
_ = td.CoaxialLumpedResistor(
resistance=50.0,
center=[0, 0, np.inf],
outer_diameter=3,
inner_diameter=1,
normal_axis=1,
name="R",
)
47 changes: 37 additions & 10 deletions tests/test_components/test_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,15 @@ def test_plot_boundaries():
plt.close()


def test_plot_with_lumped_elements():
load = td.LumpedResistor(
center=(0, 0, 0), size=(1, 2, 0), name="resistor", voltage_axis=0, resistance=50
)
sim_test = SIM_FULL.updated_copy(lumped_elements=[load])
sim_test.plot(z=0)
plt.close()


def test_wvl_mat_grid():
td.Simulation.wvl_mat_min.fget(SIM_FULL)

Expand Down Expand Up @@ -2398,7 +2407,6 @@ def test_to_gds(tmp_path):
def test_sim_subsection(unstructured, nz):
region = td.Box(size=(0.3, 0.5, 0.7), center=(0.1, 0.05, 0.02))
region_xy = td.Box(size=(0.3, 0.5, 0), center=(0.1, 0.05, 0.02))
_ = td.Box(size=(0, 0.5, 0.7), center=(0.1, 0.05, 0.02))

sim_red = SIM_FULL.subsection(region=region)
assert sim_red.structures != SIM_FULL.structures
Expand Down Expand Up @@ -2809,19 +2817,38 @@ def test_suggested_mesh_overrides():
lumped_elements=[resistor],
)

suggested_mesh_overrides = sim.suggest_mesh_overrides()
assert len(suggested_mesh_overrides) == 2
grid_spec = sim.grid_spec.copy(
update={
"override_structures": list(sim.grid_spec.override_structures)
+ suggested_mesh_overrides,
}
def update_sim_with_suggested_overrides(sim):
suggested_mesh_overrides = sim.suggest_mesh_overrides()
assert len(suggested_mesh_overrides) == 2
grid_spec = sim.grid_spec.copy(
update={
"override_structures": list(sim.grid_spec.override_structures)
+ suggested_mesh_overrides,
}
)

return sim.updated_copy(
grid_spec=grid_spec,
)

_ = update_sim_with_suggested_overrides(sim)

coax_resistor = td.CoaxialLumpedResistor(
resistance=50.0,
center=[0, 0, 0],
outer_diameter=2,
inner_diameter=0.5,
normal_axis=0,
name="R",
)

_ = sim.updated_copy(
grid_spec=grid_spec,
sim = sim.updated_copy(
lumped_elements=[coax_resistor],
grid_spec=td.GridSpec.uniform(dl=0.1),
)

_ = update_sim_with_suggested_overrides(sim)


def test_run_time_spec():
run_time_spec = td.RunTimeSpec(quality_factor=3.0)
Expand Down
126 changes: 126 additions & 0 deletions tests/test_plugins/terminal_component_modeler_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import tidy3d as td
from tidy3d.plugins.smatrix import (
LumpedPort,
CoaxialLumpedPort,
TerminalComponentModeler,
)

Expand All @@ -24,6 +25,10 @@
freq_start = 1e8
freq_stop = 10e9

# Coaxial dimensions
Rinner = 0.2768 * 1e-3
Router = 1.0 * 1e-3


def make_simulation(planar_pec: bool, length: float = None, auto_grid: bool = True):
if length:
Expand Down Expand Up @@ -156,3 +161,124 @@ def make_component_modeler(
)

return modeler


def make_coaxial_simulation(length: float = None, auto_grid: bool = True):
if length:
coax_length = length
else:
coax_length = default_strip_length

# wavelength / frequency
freq0 = (freq_start + freq_stop) / 2
fwidth = freq_stop - freq_start
wavelength0 = td.C_0 / freq0
run_time = 60 / fwidth

# Spatial grid specification
if auto_grid:
grid_spec = td.GridSpec.auto(min_steps_per_wvl=10, wavelength=td.C_0 / freq_stop)
else:
grid_spec = td.GridSpec.uniform(wavelength0 / 11)

# Make structures
inner_conductor = td.Cylinder(
center=(0, 0, 0),
radius=Rinner,
length=length,
axis=2,
)

outer_1 = td.Cylinder(
center=(0, 0, 0),
radius=Router,
length=length,
axis=2,
)

outer_2 = td.Cylinder(
center=(0, 0, 0),
radius=Router * 1.1,
length=length,
axis=2,
)

outer_shell_clip = td.ClipOperation(
operation="difference", geometry_a=outer_2, geometry_b=outer_1
)

inner = td.Structure(
geometry=inner_conductor,
medium=pec,
)

outer_shell = td.Structure(
geometry=outer_shell_clip,
medium=pec,
)

structures_list = [inner, outer_shell]

# Make simulation
center_sim = [0, 0, 0]
size_sim = [
2 * Router,
2 * Router,
coax_length + 0.5 * wavelength0,
]

sim = td.Simulation(
center=center_sim,
size=size_sim,
grid_spec=grid_spec,
structures=structures_list,
sources=[],
monitors=[],
run_time=run_time,
boundary_spec=td.BoundarySpec.all_sides(boundary=td.PML()),
shutoff=1e-4,
)

return sim


def make_coaxial_component_modeler(
reference_impedance: complex = 50,
length: float = None,
port_refinement: bool = True,
auto_grid: bool = True,
**kwargs,
):
if length:
coax_length = length
else:
coax_length = default_strip_length

sim = make_coaxial_simulation(length=coax_length, auto_grid=auto_grid)

center_src1 = [0, 0, -coax_length / 2]

port_cells = None
if port_refinement:
port_cells = 21

port_1 = CoaxialLumpedPort(
center=center_src1,
outer_diameter=2 * Router,
inner_diameter=2 * Rinner,
normal_axis=2,
direction="+",
name="coax_port_1",
num_grid_cells=port_cells,
impedance=reference_impedance,
)
center_src2 = [0, 0, coax_length / 2]
port_2 = port_1.updated_copy(name="coax_port_2", center=center_src2, direction="-")
ports = [port_1, port_2]
freqs = np.linspace(freq_start, freq_stop, 100)

modeler = TerminalComponentModeler(
simulation=sim, ports=ports, freqs=freqs, remove_dc_component=False, verbose=True, **kwargs
)

return modeler
59 changes: 59 additions & 0 deletions tests/test_plugins/test_microwave.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from tidy3d.plugins.microwave import (
VoltageIntegralAxisAligned,
CurrentIntegralAxisAligned,
CustomVoltageIntegral2D,
CustomCurrentIntegral2D,
ImpedanceCalculator,
)

Expand Down Expand Up @@ -379,3 +381,60 @@ def test_coupled_microstrip_model():
assert np.isclose(Z_odd, 39, rtol=0.01)
assert np.isclose(eps_even, 3.42, rtol=0.01)
assert np.isclose(eps_odd, 2.80, rtol=0.01)


def test_frequency_monitor_custom_voltage_integral():
length = 0.5
size = [0, 0, 0]
size[1] = length
# Make line
vertices = [(0, 0), (0, 0.2), (0, 0.4)]
voltage_integral = CustomVoltageIntegral2D(axis=2, position=0, vertices=vertices)
voltage_integral.compute_voltage(SIM_Z_DATA["field"])


def test_vertices_validator_custom_current_integral():
length = 0.5
size = [0, 0, 0]
size[1] = length
# Make wrong box
vertices = [(0.2, -0.2, 0.5), (0.2, 0.2), (-0.2, 0.2), (-0.2, -0.2), (0.2, -0.2)]

with pytest.raises(pydantic.ValidationError):
_ = CustomCurrentIntegral2D(axis=2, position=0, vertices=vertices)

# Make wrong box shape
vertices = [(0.2, 0.2, -0.2, -0.2, 0.2), (-0.2, 0.2, 0.2, -0.2, 0.2)]
with pytest.raises(pydantic.ValidationError):
_ = CustomCurrentIntegral2D(axis=2, position=0, vertices=vertices)


def test_fields_missing_custom_current_integral():
length = 0.5
size = [0, 0, 0]
size[1] = length
# Make box
vertices = [(0.2, -0.2), (0.2, 0.2), (-0.2, 0.2), (-0.2, -0.2), (0.2, -0.2)]
current_integral = CustomCurrentIntegral2D(axis=2, position=0, vertices=vertices)
with pytest.raises(DataError):
current_integral.compute_current(SIM_Z_DATA["ExHx"])


def test_time_monitor_custom_current_integral():
length = 0.5
size = [0, 0, 0]
size[1] = length
# Make box
vertices = [(0.2, -0.2), (0.2, 0.2), (-0.2, 0.2), (-0.2, -0.2), (0.2, -0.2)]
current_integral = CustomCurrentIntegral2D(axis=2, position=0, vertices=vertices)
current_integral.compute_current(SIM_Z_DATA["field_time"])


def test_mode_solver_custom_current_integral():
length = 0.5
size = [0, 0, 0]
size[1] = length
# Make box
vertices = [(0.2, -0.2), (0.2, 0.2), (-0.2, 0.2), (-0.2, -0.2), (0.2, -0.2)]
current_integral = CustomCurrentIntegral2D(axis=2, position=0, vertices=vertices)
current_integral.compute_current(SIM_Z_DATA["mode"])
Loading

0 comments on commit 1e48527

Please sign in to comment.