Monitors#
Overview#
The full space-time distribution of the EM field is typically too large to efficiently store on disk or send over networks. Instead, we use monitors to record specific subsets of the field distribution, or derived quantities, that are relevant to our simulation goals.
The types of monitors in Tidy3D include:
Field: Records the EM field components in a spatial region (from 0D up to 3D) at specified time or frequency points
Flux: Records EM power flow across a 2D surface or 3D bounding box at specified time or frequency points
Mode: Records mode coefficient(s) of the field across a 2D plane, at specified frequency points or as a time series
Diffraction: Records diffraction coefficient(s) in a periodic simulation
Far-field: Various monitors for calculating far-field projection and radiation characteristics
Surface: Records EM fields on PEC and lossy metal surfaces in a 3D region at specified time or frequency points
Permittivity and Permeability: Records material permittivity or permeability properties within a given region
See also
To learn more about accessing and plotting monitor data, please refer to the following learning center articles:
Field#
|
|
|
|
|
|
|
The FieldMonitor records the EM field components within a spatial region at
specified frequency point(s). The PointCloudFieldMonitor records
frequency-domain EM field components at arbitrary point coordinates. The
DipoleEmissionMonitor records reduced dipole-emission radiation intensity at
point-cloud positions and is typically created by the
dipole emission plugin. The
FieldTimeMonitor does the same as FieldMonitor, except at specified time
intervals instead of frequency.
Point-cloud field data is indexed by point rather than by structured x / y / z grid coordinates, so structured-grid plotting helpers such as SimulationData.plot_field() do not support PointCloudFieldData.
For point-cloud monitors, Dx, Dy, and Dz store electric displacement divided by epsilon_0 (D / epsilon_0), where epsilon_0 is the vacuum permittivity. They are reconstructed from raw E-field samples and the matching directional relative permittivity on the Yee grid: Dx uses Ex with x-direction permittivity, Dy uses Ey with y-direction permittivity, and Dz uses Ez with z-direction permittivity. The reconstructed values have the same units as the electric field.
# define a 2D field monitor at frequency f0
my_field_monitor = FieldMonitor(
center=(0,0,0),
size=(10,10,0),
name='My field monitor',
freqs=[f0],
)
# define a point-cloud field monitor at arbitrary coordinates
my_point_cloud_monitor = PointCloudFieldMonitor(
points=PointDataArray(
[[0.0, 0.0, 0.0], [0.1, 0.2, 0.3]],
coords={"index": [0, 1], "axis": [0, 1, 2]},
),
fields=["Ex", "Hy"],
name='My point-cloud monitor',
freqs=[f0],
)
# define a 1D field-time monitor starting at 1ps
my_fieldtime_monitor = FieldTimeMonitor(
center=(0,0,0),
size=(10,0,0),
name='My fieldtime monitor',
start=1e-12,
interval=50, # number of solver time steps between each measurement
)
Note
The amount of data generated can be very large when recording 2D or 3D field information across a large number of time or frequency points. To save space, consider using the interval_space parameter to downsample the grid resolution, or the interval, freqs parameters to reduce the number of time/frequency points.
Flux#
|
|
|
The FluxMonitor records EM power flux through a 2D surface or 3D bounding box at specified frequency point(s). The FluxTimeMonitor does the same, except at specified time intervals instead of frequency.
# define 2D flux monitor at frequency f0
# to record power flux in the +z direction
my_flux_monitor = FluxMonitor(
center=(0,0,0),
size=(10,10,0),
name='My flux monitor',
normal_dir='+',
freqs=[f0],
)
# define a 3D flux-time monitor to record outgoing power vs time
my_fluxtime_monitor = FluxTimeMonitor(
center=(0,0,0),
size=(10,10,10),
name='My flux-time monitor',
interval=50, # number of solver time steps between each measurement
)
See also
Example applications:
Mode#
Stores specifications for the mode solver to find an electromagnetic mode. |
|
|
|
|
|
|
The ModeMonitor records the mode coefficients of the incident field at specified frequency point(s).
Behind the scenes, a mode solver simulation is first performed to determine the eigenmodes in the ModeMonitor plane. A ModeSpec instance is necessary to provide the settings for this calculation. Then, the resulting modes are used to calculate the mode coefficients. The user does not need to explicitly perform the mode solver simulation, as it is automatically performed whenever a ModeSource or ModeMonitor is present in the simulation.
# define a mode spec
# search for 3 modes near effective index of 2.2
my_mode_spec = ModeSpec(num_modes=3, target_neff=2.2)
# define a mode monitor at 20 freq points between 240 and 300 THz
my_mode_monitor = ModeMonitor(
center=(10,0,0),
size=(0,20,20),
name='My mode monitor',
freqs=np.linspace(240e12, 300e12, 20),
mode_spec=my_mode_spec,
)
The ModeTimeMonitor is the time-domain counterpart of the ModeMonitor: instead of recording mode coefficients at discrete frequency points, it records a complex-valued modal amplitude time series for each mode and propagation direction at the monitor plane. The modes are solved at a single frequency (freq_spec, defaulting to the central frequency of the first source).
# define a mode-time monitor recording modal amplitudes from 1ps to 5ps
my_mode_time_monitor = ModeTimeMonitor(
center=(10,0,0),
size=(0,20,20),
name='My mode time monitor',
start=1e-12,
stop=5e-12,
mode_spec=my_mode_spec,
)
See also
For more details and examples, please refer to the following learning center article:
Example applications:
Diffraction#
|
The DiffractionMonitor records the diffraction coefficients of the allowed diffraction orders in a periodic simulation.
# define a diffraction monitor at 20 freq points between 250 and 300 THz
# for outgoing fields in the +z direction
my_diffraction_monitor = DiffractionMonitor(
center=(0,0,10),
size=(td.inf, td.inf, 0), # extend monitor to simulation edges
freqs=np.linspace(250e12, 300e12, 20),
name='My diffraction monitor',
normal_dir='+',
)
For more detailed examples, please refer to the demo models linked below.
See also
Example applications:
Gaussian Overlap#
|
|
|
|
|
These monitors decompose fields onto Gaussian or thin-lens beams to record overlap amplitudes.
Use ThinLensOverlapMonitor with the same thin-lens parameters as a
ThinLensBeam source to measure coupling into the corresponding focused beam. The
monitor uses the same vectorial thin-lens angular spectrum as the source and analytic
beam profile. The numerical_aperture may exceed one in high-index media as long as
it is less than the real background refractive index. Gaussian-like overlap monitor
planes must lie in a homogeneous, isotropic background medium.
thin_lens_overlap = ThinLensOverlapMonitor(
center=(0, 0, 0),
size=(0, td.inf, td.inf),
freqs=[f0],
name='thin_lens_overlap',
numerical_aperture=0.45,
waist_distance=0.0,
fill_lens=True,
num_plane_waves=51,
pol_angle=0,
)
The monitor plane should be placed on the desired beam cross section, and
waist_distance should describe that plane’s signed axial distance from focus in the
beam propagation frame. If the monitor is used to analyze fields propagated from a
ThinLensBeam source, update waist_distance by the source-to-monitor separation
along the tilted beam axis. For angled beams, also place the monitor center on the
tilted optical axis at the monitor plane. If d is the signed source-to-monitor
separation along the monitor normal coordinate, shift the two transverse coordinates by
d * tan(angle_theta) * (cos(angle_phi), sin(angle_phi)) in the monitor transverse-axis
order.
lens_offset shifts the ideal focal field in the two tangential directions through a
pupil phase ramp. The entries follow the tangential-axis order obtained by removing the
normal axis from (x, y, z); for example, a y-normal monitor uses (x, z). It does
not model a decentered finite aperture with clipping or changed pupil amplitude.
For angled monitors, angle_theta and angle_phi rotate the ideal focused beam and
its pupil. As with ThinLensBeam, this describes a tilted optical axis with an ideal
pupil perpendicular to the axis, not aberrated focusing from an obliquely illuminated
fixed lens surface.
Far-field#
|
|
|
|
|
|
|
|
|
The far-field monitor records the near-field within the simulation domain in order to project it to some far away location. This can be a very efficient way to simulate the scattering or radiative response of devices such as lenses and antenna.
# define a far-field monitor
my_far_field_monitor = FieldProjectionCartesianMonitor(
center=(0,0,10),
size=(td.inf, td.inf, 0),
name="My far field",
freqs=[f0],
far_field_approx=True,
proj_axis=2,
proj_distance=20,
x=np.linspace(-10,10,101),
y=np.linspace(-10,10,101),
)
The far_field_approx parameter should be set to True (default) when the projection plane is far from the simulation domain. For intermediate distances, the user can set it to False for increased accuracy at the expense of slightly greater computational cost.
When including far-field projection monitors in the Simulation object, the far-field calculation is performed server-side. The computation is much faster and slightly more accurate than if performed locally. However, it will slightly increase the cost of the simulation.
Projection of near fields to points on a given observation grid. |
|
Data structure to store surface monitors where near fields are recorded for field projections. |
The user also has the option of performing the far-field calculation on their local machine using FieldProjector object. In that case, they should first set up one or more FieldMonitor in the simulation. After the simulation is completed, the FieldProjector object operates on the recorded field data.
# define a far-field projector from previously defined field monitors
my_far_field_projector = FieldProjector.from_near_field_monitors(
sim_data = simulation_data, # previously computed simulation data
near_monitors = [monitor1], # list of previously defined near field monitors
normal_dirs=['+'], # projection direction relative to monitor
pts_per_wavelength=10 # controls sampling rate (reduce to speed up computation)
)
# project field based on previously defined far-field monitor
projected_field = my_far_field_projector.project_fields(my_far_field_monitor)
Please see the learning center article below for detailed explanations on additional settings and usage scenarios.
See also
For more details and examples, please refer to the following learning center article:
Example applications:
Surface#
|
|
|
The SurfaceFieldMonitor records electromagnetic fields on PEC (PECMedium) and lossy metal (LossyMetalMedium) with penetrable=False within a 3D region at specified frequency point(s). The SurfaceFieldTimeMonitor does the same, except at specified time intervals instead of frequency. These monitors store the normal E and tangential H fields on these surfaces.
# define a frequency-domain surface field monitor
my_surface_monitor = SurfaceFieldMonitor(
center=(1,2,3),
size=(2,2,2),
fields=['E', 'H'],
freqs=[250e12, 300e12],
name='surface_monitor',
)
# define a time-domain surface field monitor
my_surface_time_monitor = SurfaceFieldTimeMonitor(
center=(1,2,3),
size=(2,2,2),
fields=['H'],
start=1e-13,
stop=5e-13,
interval=2,
name='surface_time_monitor',
)
Note
Surface monitors are currently in beta stage. Please exercise caution when analyzing surface monitor data and verify results carefully.
Permittivity and Permeability#
|
|
|
|
|
The PermittivityMonitor is used to record local relative permittivity data in the region of interest, and the PointCloudPermittivityMonitor records local relative permittivity components for arbitrary requested point coordinates. PermittivityMonitor, PointCloudPermittivityMonitor, and MediumMonitor return material values on the simulation Yee grid. Near material interfaces, these may be effective grid values representing the discretized interface rather than the bulk value of exactly one adjacent material. The monitors do not apply additional interpolation or smoothing to user-requested coordinates. For PointCloudPermittivityMonitor, each returned component is sampled from its nearest native Yee-grid location, using the eps_xx / eps_yy / eps_zz component grids associated with Ex / Ey / Ez respectively; values are not interpolated to the exact requested coordinates. The returned .points array stores the requested point cloud, not the snapped component-grid sampling locations. The MediumMonitor can additionally record permeability data. Those data can be useful for post-simulation calculations that require permittivity or permeability values, such as mode volume and absorption density.
Point-cloud permittivity data is indexed by point rather than by structured x / y / z grid coordinates. Access the components directly, for example sim_data["my point-cloud permittivity monitor"].eps_xx, and inspect the requested coordinates with sim_data["my point-cloud permittivity monitor"].points.
my_permittivity_monitor = PermittivityMonitor(
center=(0,0,0),
size=(8,8,8),
freqs=[250e12, 300e12],
name='my permittivity monitor',
)
my_point_cloud_permittivity_monitor = PointCloudPermittivityMonitor(
points=PointDataArray(
[[0.0, 0.0, 0.0], [0.1, 0.2, 0.3]],
coords={"index": [0, 1], "axis": [0, 1, 2]},
),
freqs=[250e12, 300e12],
name='my point-cloud permittivity monitor',
)
Apodization#
Stores specifications for the apodizaton of frequency-domain monitors. |
The ApodizationSpec is used to specify apodization specifications for frequency-domain monitors. Typically, the default Tidy3D settings are acceptable and it is not necessary to define a custom instance. Please refer to the documentation page for more details.