S-Matrix Component Modelers Plugin#

tidy3d.plugins.smatrix.ModalComponentModeler

A tool for modeling devices and computing scattering matrix elements.

tidy3d.plugins.smatrix.ModalComponentModelerData

A data container for the results of a ModalComponentModeler run.

tidy3d.plugins.smatrix.Port

Specifies a port for S-matrix calculation.

tidy3d.plugins.smatrix.ModalPortDataArray

Port parameter matrix elements for modal ports.

See also

For classes related to microwave/RF modeling, please refer to the main Microwave and RF page.

Warning

RF simulations will be subject to new license requirements in the future.

TerminalComponentModeler#

tidy3d.plugins.smatrix.TerminalComponentModeler

Tool for modeling two-terminal multiport devices and computing port parameters with lumped and wave ports.

tidy3d.plugins.smatrix.TerminalComponentModelerData

Data associated with a TerminalComponentModeler simulation run.

tidy3d.plugins.smatrix.MicrowaveSMatrixData

Stores the computed S-matrix and reference impedances for the terminal ports.

tidy3d.plugins.smatrix.TerminalPortDataArray

Port parameter matrix elements for terminal-based ports.

tidy3d.plugins.smatrix.PortDataArray

Array of values over dimensions of frequency and port name.

The TerminalComponentModeler is the core simulation object for 3D RF/microwave simulations in Tidy3D. Its primary function is to simulate the system over N number of ports and M number of frequency points, with the end result being a MxNxN S-parameter matrix.

my_tcm = TerminalComponentModeler(
    simulation=base_sim,
    ports=[port1, port2],
    freqs=my_frequencies,
    ...
)

The key parts of a TerminalComponentModeler are:

  • The Simulation field defines the underlying Tidy3D Simulation object. This base Simulation object contains information about the simulation domain such as structures, boundary conditions, grid specifications, and monitors. Note that sources should not be included in the base simulation, but rather in the ports field instead.

  • The ports field defines the list of source excitations. These are commonly of type LumpedPort or WavePort. The number of ports determines the number of batch jobs in the TerminalComponentModeler and the dimensionality of the S-parameter matrix.

  • The freqs field defines the list of frequency points for the simulation.

More information and explanation for additional fields can be found in the documentation page for the TerminalComponentModeler. In order to submit the simulation, use tidy3d.web.upload(), tidy3d.web.start(), tidy3d.web.monitor(), and tidy3d.web.load().

# Upload simulation and get cost estimate
my_task_id = tidy3d.web.upload(my_tcm, task_name='my_task_name')

# Run simulation
tidy3d.web.start(my_task_id)

# Monitor simulation
tidy3d.web.monitor(my_task_id)

# Load results after completion
my_tcm_data = tidy3d.web.load(my_task_id)

Alternatively, use the tidy3d.web.run() method to perform all of the above in one single step.

# Upload, run simulation, and download data
my_tcm_data = tidy3d.web.run(my_tcm, task_name='my_task_name', path='my/local/download/path')

To get the S-matrix from the results, use the smatrix() method of the TerminalComponentModelerData object.

# Get S-matrix from results
my_s_matrix = my_tcm_data.smatrix()

The S-matrix is stored as a MicrowaveSMatrixData whose data property contains a TerminalPortDataArray instance. To obtain a specific S_ij value, use the port_in and port_out coordinates with the corresponding port name. To obtain a specific frequency, use the f coordinate.

# Get return loss
my_S11 = my_s_matrix.data.sel(port_in="my_port_1", port_out="my_port_1")

Note

At this moment, Tidy3D uses the physics phase convention \(e^{-i\omega t}\). Other RF simulation software and texts may use the electrical engineering convention \(e^{i\omega t}\). This affects the calculated S-parameters and impedance values. To convert between the two, simply use the complex conjugation operation, e.g. np.conjugate().

To access simulation data for a given port excitation, use the data attribute of the TerminalComponentModelerData.

# Get simulation data for a given port "my_port"
sim_data = my_tcm_data.data["my_port"]

# Get monitor data from a given monitor "my_monitor"
my_monitor_data = sim_data["my_monitor"]

The data attribute holds the simulation data in a dictionary with the respective port name as keys. The data for each monitor can then be accessed from the simulation data object using the monitor name as the dictionary key.

See also

To learn more about the web API workflow in Tidy3D, please refer to the following pages:

To learn more about data post-processing and visualization, please refer to the following pages:

Please refer to the following example models to see the TerminalComponentModeler in action:


RF Materials Models#

tidy3d.PECMedium

Perfect electrical conductor class.

tidy3d.PMCMedium

Perfect magnetic conductor class.

tidy3d.LossyMetalMedium

Lossy metal that can be modeled with a surface impedance boundary condition (SIBC).

tidy3d.SurfaceImpedanceFitterParam

Advanced parameters for fitting surface impedance of a LossyMetalMedium.

tidy3d.HammerstadSurfaceRoughness

Modified Hammerstad surface roughness model.

tidy3d.HuraySurfaceRoughness

Huray surface roughness model.

The PECMedium and LossyMetalMedium classes can be used to model metallic materials.

# lossless metal
my_pec = PECMedium()

# lossy metal (conductivity in S/um)
my_lossy_metal = LossyMetalMedium(conductivity=58, freq_range=(1e9, 10e9))

Note that the unit of conductivity is S/um and the unit of freq_range is Hz. The LossyMetalMedium class implements the surface impedance boundary condition (SIBC). It can accept surface roughness specifications using the Hammerstad or Huray models. Please refer to their respective documentation pages for details. Edge singularity correction is also available but turned off by default at this time.

Note

When modeling lossy metals, always be sure to check the skin depth — if the skin depth is significant compared to the geometry size, then LossyMetalMedium may be not accurate. In that case, use a regular dispersive medium instead.

tidy3d.Medium

Dispersionless medium.

tidy3d.plugins.dispersion.FastDispersionFitter

Tool for fitting refractive index data to get a dispersive medium described by PoleResidue model.

To model lossless dielectrics, use the regular Medium.

# lossless dielectric
my_lossless_dielectric = Medium(permittivity=2.2)

To model a lossy dielectric with constant loss tangent, use the constant_loss_tangent_model() method of the tidy3d.plugins.dispersion.FastDispersionFitter utility class.

# lossy dielectric (constant loss tangent)
my_lossy_dielectric = FastDispersionFitter.constant_loss_tangent_model(
    eps_real=4.4,
    loss_tangent=0.002,
    frequency_range=(1e9, 5e9)
)

More advanced material models, including frequency dependence and anisotropy, are also available in Tidy3D.

See also

For a more comprehensive discussion of the different EM mediums available in Tidy3D, please refer to the EM Mediums page:


Lumped Port & Elements#

tidy3d.plugins.smatrix.LumpedPort

Class representing a single rectangular lumped port.

tidy3d.plugins.smatrix.CoaxialLumpedPort

Class representing a single coaxial lumped port.

The LumpedPort feature represents a planar, uniform current excitation with a fixed impedance termination.

# Define a lumped port
my_port_1 = LumpedPort(
    name="My Port 1",
    center=(0,0,0),
    size=(0, port_width, port_height),
    voltage_axis=2,   # z-axis aligned excitation
    impedance=50,   # port impedance
)

The LumpedPort can be 1D (line) or 2D (plane). For 2D, only axis-aligned planes are supported at this time. Only real impedance values are supported at this time.

Note

Lumped ports and elements are fundamentally approximations and thus should only be used when the port/element size is much smaller than the wavelength of interest (typically lambda/10). For more accurate results, especially when the port is adjacent to an intentional waveguide or transmission line, consider using the WavePort excitation instead.

The CoaxialLumpedPort represents an analytical coaxial field source.

# Define coaxial lumped port
my_coaxial_port_1 = CoaxialLumpedPort(
    name="My Coaxial Port 1",
    center=(0,0,0),
    inner_diameter=1000,   # inner diameter in um
    outer_diameter=2000,   # outer diameter in um
    normal_axis=0,   # normal axis to port plane
    direction="+",   # direction of signal along normal axis
    impedance=50,   # port impedance
)

Note

Because the CoaxialLumpedPort injects an analytical field source, the structure connected to this port must match the physical port dimensions. Any deviation will result in signal reflection and potential inaccuracies. One common source of this issue is in imported geometries with faceted cylinders.

tidy3d.LumpedResistor

Class representing a rectangular lumped resistor.

tidy3d.CoaxialLumpedResistor

Class representing a coaxial lumped resistor.

tidy3d.LinearLumpedElement

Lumped element representing a network consisting of resistors, capacitors, and inductors.

tidy3d.RLCNetwork

Class for representing a simple network consisting of a resistor, capacitor, and inductor.

tidy3d.AdmittanceNetwork

Class for representing a network consisting of an arbitrary number of resistors, capacitors, and inductors.

For a simple resistive lumped element, use LumpedResistor.

my_resistor = LumpedResistor(
    name="My resistor",
    center=(0,0,0),
    size=(0, element_width, element_height),
    voltage_axis=2,   # z-axis aligned
    resistance=50,   # real-valued impedance
)

For more complicated RLC networks, use the general LinearLumpedElement class.

my_lumped_element = LinearLumpedElement(
    name="My lumped element",
    center=(0,0,0),
    size=(0, element_width, element_height),
    voltage_axis=2,   # z-axis aligned
    network=RLCNetwork(resistance=50, inductance=1e-9)  # RLC network
)

All lumped elements should be added to the lumped_elements field of the base Simulation instance.

my_simulation = Simulation(
    lumped_elements=[my_resistor, my_lumped_element],
    ...,
)

See also

For more in-depth discussion and examples, please see the following learning center article:

Example applications:


Wave Port#

tidy3d.plugins.smatrix.WavePort

Class representing a single wave port

tidy3d.ModeSpec

Stores specifications for the mode solver to find an electromagnetic mode.

The WavePort represents a modal source port. The port mode is first calculated in the 2D mode solver, then injected into the 3D simulation. The WavePort is also automatically terminated with a modal absorbing boundary ModeABCBoundary that perfectly absorbs the outgoing mode. Any non-matching modes are subject to PEC reflection.

my_wave_port_1 = WavePort(
    center=(0,0,0),
    size=(port_width, port_height, 0),
    name='My Wave Port 1',
    direction='+',  # direction of signal
    mode_spec=ModeSpec(target_neff=1.5),  # specification for mode solver
    current_integral=my_current_integral,  # current integration curve for port impedance calculation
)

Most fields are self explanatory. Some additional notes:

  • mode_spec is used to specify the effective index search value for the mode solver

  • current_integral and/or voltage_integral are used to specify the integration paths for port impedance calculation. If only one of the two is specified, then the port power is also used (automatically determined).

If it is desired to only solve for the 2D port mode, one can use the to_mode_solver() convenience method to generate a ModeSolver simulation object.

# Define a mode solver from the wave port
my_mode_solver = my_wave_port_1.to_mode_solver(
    simulation=base_sim,   # base Simulation object
    freqs=my_frequencies,   # frequencies for 2D mode solver
)

# Execute mode solver
my_mode_data = web.run(my_mode_solver, task_name='mode solver')

tidy3d.plugins.microwave.AxisAlignedVoltageIntegral

Class for computing the voltage between two points defined by an axis-aligned line.

tidy3d.plugins.microwave.AxisAlignedCurrentIntegral

Class for computing conduction current via Ampère's circuital law on an axis-aligned loop.

tidy3d.plugins.microwave.Custom2DVoltageIntegral

Class for computing the voltage between two points defined by a custom path.

tidy3d.plugins.microwave.Custom2DCurrentIntegral

Class for computing conduction current via Ampère's circuital law on a custom path.

tidy3d.plugins.microwave.AxisAlignedPathIntegral

Class for defining the simplest type of path integral, which is aligned with Cartesian axes.

tidy3d.plugins.microwave.Custom2DPathIntegral

Class for defining a custom path integral defined as a curve on an axis-aligned plane.

tidy3d.plugins.microwave.ImpedanceCalculator

Tool for computing the characteristic impedance of a transmission line.

The classes above are used to define the voltage/current integration paths for impedance calculation.

# Define voltage integration line
my_voltage_integral = AxisAlignedVoltageIntegral(
    center=(0,0,0),  # center of integration line
    size=(5, 0, 0),  # length of integration line
    sign='+',  # sign of integral
)

# Define current integration loop
my_current_integral = AxisAlignedCurrentIntegral(
    center=(0,0,0),  # center of integration loop
    size=(20, 20, 0),  # size of integration loop
    sign='+', # sign of integral (should match wave port direction)
)

In addition to being used in the WavePort definition, the current/voltage integration objects can also be applied to arbitrary EM field data (2D and 3D). This is most commonly used in conjunction with the ImpedanceCalculator to calculate the line impedance of a 2D mode.

# Define impedance calculator
my_Z_calculator = ImpedanceCalculator(
    voltage_integral = my_voltage_integral,
    current_integral = my_current_integral,
)

# Calculate impedance of 2D mode
Z_mode = my_Z_calculator.compute_impedance(my_mode_data)

As before, only one of the two integration paths (voltage or current) are strictly necessary. This determines the convention used to calculate the impedance (PI, PV, or VI).

See also

For more information, please see the following articles:

Example applications:


v2.10 Refactor Migration#

In version v2.10.0rc1, smatrix plugin classes were refactored to improve web and GUI support for RF capabilities. This guide helps you update your scripts to the new, more robust API.

Key Changes#

  • Rename: ComponentModeler has been renamed ModalComponentModeler.

  • Web Interface: Web parameters like verbose and path_dir are now passed to tidy3d.web.run() instead of the modeler class constructor.

  • Immutable Data Structures: Modeler classes are now immutable. ComponentModelerData classes hold simulation results, separating data from the modeler definition.

  • Explicit Method Calls: Running simulations and fetching results are now done through explicit function calls like tidy3d.web.run() and tidy3d.web.load().

Updated Workflow#

The new workflow is more explicit and aligns with the general tidy3d API.

Before (Old API):

import tidy3d.plugins.smatrix as sm

# Modeler class was mutable and included web parameters
tcm = sm.TerminalComponentModeler(
    simulation=sim,
    ports=[LP1, LP2],
    freqs=freqs,
    verbose=True,
    path_dir="data",
)
# The run method was part of the modeler class
s_matrix = tcm.run()

After (New API):

import tidy3d.web as web
import tidy3d.plugins.smatrix as sm

# Modeler class is now immutable and cleaner
tcm = sm.TerminalComponentModeler(
    simulation=sim,
    ports=[LP1, LP2],
    freqs=my_freqs,
)
# Use web.run to execute the simulation
modeler_data = web.run(tcm, verbose=True, path="data/modeler_data.hdf5")
s_matrix = modeler_data.smatrix()

Note

The S-matrix is now computed from the ComponentModelerData objects, so it is accessed via the .smatrix() method.

Cost Estimation#

Cost estimation is now done by uploading the modeler to the web API.

Before:

est_flex_credits = tcm.estimate_cost()
real_flex_credits = tcm.real_cost()

After:

task_id = web.upload(tcm)
est_flex_credits = web.estimate_cost(task_id)
# After the run is complete
real_flex_credits = web.real_cost(task_id)

Data Handling#

The new API introduces immutable data containers for simulation results, ensuring that your data is more predictable and easier to manage.

These data objects contain the S-matrix, port impedance, and other relevant results.

Before:

# batch_data was a mutable property of the modeler
tcm_batch = tcm.batch_data
sim_data = tcm_batch["smatrix_LP1"]

After:

# web.run returns an immutable data object
modeler_data = web.run(tcm)
# Access simulation data for each port
sim_data = modeler_data.data["smatrix_LP1"]

Migration Utilities#

To ease the transition, we provide utilities that mimic the old workflow.

Warning

These migration helpers are temporary and will be deprecated in a future release.

  • Run a batch of simulations: If you prefer to manage the batch run yourself, you can create and run a batch explicitly.

    from tidy3d.plugins.smatrix.run import create_batch
    
    batch = create_batch(modeler=my_modeler)
    batch_data = batch.run()
    
  • Compose data from a batch: If you have a tidy3d.web.BatchData object from a manual run, you can still create the corresponding ModalComponentModelerData or TerminalComponentModelerData object.

    from tidy3d.plugins.smatrix.run import compose_modeler_data_from_batch_data
    
    modeler_data = compose_modeler_data_from_batch_data(
        modeler=my_modeler, batch_data=batch_data
    )
    

API Reference#

For more details, see the API documentation for the new classes and functions:

tidy3d.plugins.smatrix.ModalComponentModeler

A tool for modeling devices and computing scattering matrix elements.

tidy3d.plugins.smatrix.ModalComponentModelerData

A data container for the results of a ModalComponentModeler run.

tidy3d.plugins.smatrix.TerminalComponentModeler

Tool for modeling two-terminal multiport devices and computing port parameters with lumped and wave ports.

tidy3d.plugins.smatrix.TerminalComponentModelerData

Data associated with a TerminalComponentModeler simulation run.

tidy3d.SimulationMap

An immutable dictionary-like container for simulations.

tidy3d.SimulationDataMap

An immutable dictionary-like container for simulation data.

tidy3d.plugins.smatrix.run.create_batch(...)

Create a simulation Batch from a component modeler.

tidy3d.plugins.smatrix.run.compose_modeler_data_from_batch_data(...)

Select the correct composer based on modeler type and create the data object.

tidy3d.plugins.smatrix.run.compose_modeler_data(...)

Create a modeler data object from a modeler and indexed simulation data.

Further Details#

tidy3d.plugins.smatrix.AbstractComponentModeler

Tool for modeling devices and computing port parameters.

tidy3d.SimulationMap

An immutable dictionary-like container for simulations.

tidy3d.SimulationDataMap

An immutable dictionary-like container for simulation data.