RF Simulation Overview
This page introduces the basic concepts of running an RF simulation in Flexcompute RF (also Flex RF).
Default Units
Section titled “Default Units”The following are the default units used by the RF solver, largely based on the SI convention. The key difference is that the default length unit is the micrometer ( meters).
| Physical quantity | Default unit |
|---|---|
| Length | micrometer (um) |
| Time | second (s) |
| Current | Ampere (A) |
The following constants are available, defined based on the default unit system.
| Constant | Description | Unit |
|---|---|---|
C_0 | Speed of light | um/s |
EPSILON_0 | Permittivity of free space | F/um |
MU_0 | Permeability of free space | H/um |
ETA_0 | Impedance of free space | Ohm |
inf | Infinity (effective) | None |
Finally, note that the RF solver uses the physics phase convention , rather than the engineering phase convention . This means that complex quantities like S-, Z-, Y-parameters, mode propagation constant, as well as certain lossy material coefficients may require complex conjugation when interfacing with external data.
3D Simulation
Section titled “3D Simulation”The TerminalComponentModeler is the core simulation object for 3D microwave analysis. Its main function is to perform a sweep over N ports/modes across M frequency points, then return an M x N x N S-parameter matrix.
Basic structure
Section titled “Basic structure”TerminalComponentModeler├── simulation # Base simulation│ ├── center, size # Simulation domain center and size│ ├── structures # List of physical structures (geometry + medium)│ ├── monitors # List of user-specified monitors│ ├── grid_spec # Specification for FDTD grid│ ├── boundary_spec # Specification for external boundary conditions│ ├── lumped_elements # List of lumped elements (if present)│ ├── run_time # Length of simulated time (unit: s)│ └── ...├── ports # List of ports to sweep├── freqs # List of frequency points├── radiation_monitors # Monitor(s) for antenna FoM calculation└── ...The TerminalComponentModeler contains a base Simulation object along with the port and frequency list information. The base Simulation contains the physical structures, monitors, lumped elements, grid and boundary settings, as well as various other detailed settings.
Typical workflow
Section titled “Typical workflow”The typical workflow is to first construct the base Simulation object. Some key parameters include:
- center and size of the simulation domain
- the physical structures
- user-specific monitors (if any)
- settings for the FDTD grid
- settings for external boundaries (if not using PMLs)
- lumped elements (if any)
- simulation run time
# Define the base simulationmy_sim = Simulation( center=(0,0,0), size=(1e5, 1e5, 1e4), structures=my_structure_list, monitors=my_monitor_list, grid_spec=my_grid_spec, run_time=1e-9,)The TerminalComponentModeler is then constructed from the base Simulation. Key parameters at this stage include:
- the base
Simulation - list of ports
- list of frequency points
# Defining the TerminalComponentModelermy_tcm = TerminalComponentModeler( simulation=my_sim, ports=[port_1, port_2], freqs=np.linspace(f_min, f_max, 401))Visualization
Section titled “Visualization”Use the plot_sim() method in TerminalComponentModeler to visualize the simulation domain in a 2D cross-section along the x, y or z axis. Use the plot_grid() method in the base Simulation to visualize the simulation grid.
fig, ax = plt.subplots(figsize=(8,6))# Plot the simulation grid at z = 30ummy_tcm.simulation.plot_grid(z=30, ax=ax)# Also plot the simulation domain (structures, ports, monitors etc.) at z = 30ummy_tcm.plot_sim(z=30, ax=ax)plt.show()Use the plot_3d() method in the base Simulation to open a 3D viewer in a Jupyter notebook.
# Launch inline 3D viewer in the Jupyter notebookmy_tcm.simulation.plot_3d()Result data
Section titled “Result data”The default output of a TerminalComponentModeler simulation is the full S-matrix.
# Submit a TCM jobmy_tcm_data = web.run(my_tcm, task_name='my tcm job')
# After job completion, access the S-matrixs_matrix = my_tcm_data.smatrix()The S-matrix is stored in an xarray-based format. Individual S_ij entries can be accessed using the sel or isel methods. Broadcasting with numpy math methods is supported.
# Access S11 using port index (zero-indexed)S11 = s_matrix.data.isel(port_in=0, port_out=0)
# Access S11 using port namesS11 = s_matrix.data.sel(port_in='my port 1', port_out='my port 1')
# Calculate the dB value of S11S11dB = 20*np.log10(np.abs(S11))If the base Simulation contains user-specified monitors, the monitor data is recorded for every instance of the port/mode sweep. In other words, if there are two single-mode ports in a TerminalComponentModeler instance, there will be two sets of recorded monitor data corresponding to each port excitation. These sets of data are stored in a dictionary format.
# Access the monitors dataset corresponding to 'port_1' excitationmy_sim_data = my_tcm_data['port_1']
# Plot the field from a user-defined FieldMonitor 'my_monitor_1'my_sim_data.plot_field(field_monitor_name="my_monitor_1", field_name="E", val="abs", f=f_min, ...)
# Access data from a user-defined FieldMonitor 'my_monitor_1'Ex = my_sim_data['my_monitor_1'].ExEy = my_sim_data['my_monitor_1'].EyEz = my_sim_data['my_monitor_1'].EzThe example code above shows how to access the data from a specific user-defined FieldMonitor corresponding to a specific port excitation. Note that different monitor types may have different data access patterns.
2D Mode Analysis
Section titled “2D Mode Analysis”The ModeSolver is the core simulation object for 2D mode analysis workflows.
Basic structure
Section titled “Basic structure”ModeSolver├── simulation # Base simulation│ ├── center, size # Simulation domain center and size│ ├── structures # List of physical structures (geometry + medium)│ ├── grid_spec # Specification for FDTD grid│ └── ...├── mode_spec # Specification for the mode calculation│ ├── num_modes # Number of modes to find│ ├── target_neff # Initial search value for effective mode index│ ├── sort_spec # Specification for mode sorting and filtering│ └── ...├── plane # 2D Box object that defines the mode solver plane├── freqs # List of frequency points├── direction # Direction of propagation along axis ('+' or '-')└── ...Like the TerminalComponentModeler, the ModeSolver also contains a base Simulation object.
Typical workflow
Section titled “Typical workflow”While the user can manually define a ModeSolver object, a more common workflow is to create the ModeSolver from a pre-defined wave port object and base Simulation. A wave port (also known as a waveguide port in other literature) represents a modal- or terminal-based excitation in a 3D simulation. More information on wave ports can be found in this article.
# Define a Simulationmy_sim = Simulation(...)
# Define a wave portmy_port = WavePort(...)
# Define a mode solver simulation from a wave portmy_mode_study = my_port.to_mode_solver( simulation=my_sim, freqs=np.linspace(f_min, f_max, 21))Visualization
Section titled “Visualization”Use the plot() and plot_grid() methods of ModeSolver to visualize the 2D mode solver domain and simulation grid, respectively.
fig, ax = plt.subplots(figsize=(8,6))# Plot the simulation grid in the mode solver planemy_mode_study.plot_grid(ax=ax)# Also plot the mode solver domainmy_mode_study.plot(ax=ax)plt.show()Result data
Section titled “Result data”The default output of a ModeSolver simulation is the found eigenmodes (field profiles) and eigenvalues (complex propagation constants) of the 2D problem.
# Submit a mode solver jobmy_mode_data = web.run(my_mode_study, task_name='my mode study')
# Plot the resulting field profile(s)my_mode_study.plot_field(field_name="E", val="abs", f=f_max, mode_index=0)
# Access mode field componentsmode_Ex = my_mode_data.Exmode_Ey = my_mode_data.Eymode_Ez = my_mode_data.EzThe mode data contains datasets organized as xarray-type data structures. This means that utility functions like sel and isel can be used to filter based on coordinates. Common coordinates include
- Mode index
mode_index - Frequency
f - Spatial coordinates
x, y, z(where applicable)
# Get Ex component of mode 0 at f=f_min and x=10 micronEx = my_mode_data.Ex.sel(mode_index=0, f=f_min, x=10)Additional physical quantities such as effective mode index, attenuation, and mode impedance are also pre-calculated.
# Access common transmission line quantitiesn_eff = my_mode_data.n_eff # Effective indexgamma = my_mode_data.gamma # Complex propagation constantZ0 = my_mode_data.transmission_line_data.Z0 # Characteristic impedance