Grid Discretization#

Overview#

In FDTD, the simulation domain is rendered onto a finite spatial grid. Each grid cell, also known as a Yee cell, represents a location where the field solution is sampled. For the FDTD user, there are two general categories of length scales to be aware of when it comes to defining the grid:

  • Physical length scale: this primarily consists of the EM wavelength in the local medium, but depending on the application, could include other quantities like mode propagation and attenuation lengths, skin depth, sharp field gradients etc.

  • Geometric length scale: this refers to the minimum feature size of the structure. Common features include layer thickness, gaps, radii of curvature, sharp corners.

To obtain good results, the minimum grid size should be small enough to resolve both categories. Note that in typical photonics applications, the physical length scale would likely dominate in importance. In contrast, for deep subwavelength problems such as those in RF/microwave regime, the geometric length scale becomes a limiting factor, especially if metallic structures are involved.

Tidy3D automatically ensures that the CFL condition is satisfied. This means that the simulation time step is constrained by the minimum grid size.

To learn how to provide a grid specification in a Tidy3D simulation, see the Grid Specification section below. The following sections cover more advanced topics, such as implementing additional grid refinement, subpixel averaging, and other utility classes.

See also

For an introduction to FDTD discretization and related topics, please see the following FDTD101 lectures:


Grid Specification#

tidy3d.GridSpec

Collective grid specification for all three dimensions.

tidy3d.AutoGrid

Specification for non-uniform grid along a given dimension.

tidy3d.UniformGrid

Uniform 1D grid.

tidy3d.QuasiUniformGrid

Similar to UniformGrid that generates uniform 1D grid, but grid positions are locally fine tuned to be snaped to snapping points and the edges of structure bounding boxes.

tidy3d.CustomGrid

Custom 1D grid supplied as a list of grid cell sizes centered on the simulation center.

tidy3d.CustomGridBoundaries

Custom 1D grid supplied as a list of grid cell boundary coordinates.

The GridSpec object in Tidy3D contains grid definition along all three spatial axes. Each spatial axis accepts one of the basic grid types, AutoGrid, UniformGrid, QuasiUniformGrid, or CustomGrid. A typical Tidy3D Simulation object contains one instance of GridSpec, which in turn contains three instances of the grid types, which specify the grid along that particular axis:

my_grid_spec = GridSpec(
    grid_x = AutoGrid(min_steps_per_wvl=16),
    grid_y = UniformGrid(dl=0.1),
    grid_z = QuasiUniformGrid(dl=0.1),
    wavelength=1.55
)

Notice in the above example that we also defined the free-space wavelength, which is necessary for the AutoGrid grid type.

Note

Note that setting wavelength in this manner is optional if there is at least one source in the simulation.

If the grid specification is the same along all three spatial axes, the user can alternatively define it inline like so:

# auto grid with 16 grid points per wavelength
my_autogrid_spec = GridSpec.auto(wavelength=1.55, min_steps_per_wvl=16)

# uniform grid with spacing of 0.1 microns
my_uniform_grid_spec = GridSpec.uniform(dl=0.1)

# quasi-uniform grid with spacing of 0.1 microns
my_quasiuniform_grid_spec = GridSpec.quasiuniform(dl=0.1)

Please find short descriptions of each grid type below. For more information, please refer to their respective documentation page.

  • The AutoGrid grid type automatically sets the grid size based on the EM wavelength in the local medium and user-specified minimum steps per wavelength. This is the default option if no grid specification is provided.

  • The UniformGrid grid type creates a uniform grid with fixed spacing dl.

  • The QuasiUniformGrid grid type behaves similarly to the UniformGrid, but respects snapping for structure boundaries.

  • The CustomGrid grid type allows the user to manually specify grid point positions.

See also

For more detail explanation and examples, please see the following learning center resources:


Refinement#

tidy3d.MeshOverrideStructure

Defines an object that is only used in the process of generating the mesh.

tidy3d.LayerRefinementSpec

Specification for automatic mesh refinement and snapping in layered structures.

tidy3d.GridRefinement

Specification for local mesh refinement that defines the grid step size and the number of grid cells in the refinement region.

tidy3d.CornerFinderSpec

Specification for corner detection on a 2D plane.

For certain applications, the user may wish to apply additional grid refinement in specific regions, layers, or points in the simulation domain. The GridSpec class accepts the following optional parameters:

  • override_structures: The user provides a list of mesh override structures to apply additional refinement to a specific region

  • snapping_points: The user specifies a list of points that enforce grid boundaries to pass through them

  • layer_refinement_specs: The user specifies additional refinement within a layered region (e.g. a metallic trace plane)

For the override_structures option, the user may provide a list consisting of Structure instances and/or MeshOverrideStructure instances. In the former case, the provided Structure is used as a fictitious material with artificially higher refractive index to enforce higher grid resolution:

# fictitious structure used for grid refinement
my_refinement_box = Structure(
    geometry=Box(center=(0,0,0), size=(1,1,1)),
    medium=Medium(permittivity=16),
)

# apply the refinement structure to the grid spec
my_refined_grid_spec = GridSpec.auto(
    wavelength=1.55,
    min_steps_per_wvl=16,
    override_structures=[my_refinement_box]
)

In the example above, the AutoGrid would generate a grid as though the region within my_refinement_box had permittivity=16, when it could be much lower in the actual structure. Note that my_refinement_box is not actually present in the simulation and is only taken into account for grid generation purposes.

The second method is to define a MeshOverrideStructure. This allows the user to specify step sizes along each direction:

# a mesh override structure that enforces step size dx=0.1 and dz=0.2
my_mesh_override_structure = MeshOverrideStructure(
    geometry=Box(center=(0,0,0), size=(1,1,1)),
    dl=(0.1, None, 0.2),
)

The LayerRefinementSpec class allows the user to specify added refinement to a layered region (e.g. a metallic trace plane). Within the layer, the grid can be snapped to structure corners. Along the layer normal axis, the grid can also be snapped to the layer bounds.

my_layer_refinement_spec = LayerRefinementSpec(
    axis=2,
    center=(0, 0, 0),
    size=(3, 2, 0.1),
    min_steps_along_axis=4,  # minimum 4 grid points along the layer normal axis
    bounds_snapping='bounds',  # snap grid boundaries to upper and lower layer boundaries
    corner_snapping=True,  # snap grid points to structure corners
)

For more detailed usage examples of LayerRefinementSpec, please refer to the learning center article linked below.

See also

For more detail explanation and examples, please see the following learning center resources:


Subpixel Averaging#

tidy3d.SubpixelSpec

Defines specification for subpixel averaging schemes when added to Simulation.subpixel.

Subpixel averaging is used to accurately resolve material boundaries which do not line up with the grid boundaries. Under normal circumstances, the default settings are appropriate and the user does not need to provide a custom SubpixelSpec.

More advanced users may opt to define a custom SubpixelSpec. The custom SubpixelSpec instance is then passed into the Simulation object as a parameter.

my_custom_subpixel_spec = SubpixelSpec(
    dielectric=PolarizedAveraging(),
    metal=Staircasing(),
    pec=PECConformal(),
    lossy_metal=SurfaceImpedance(),
)

In the example above, the chosen method of subpixel averaging is specified for each material type. For more details on each subpixel averaging method, please refer to their respective documentation pages below.

tidy3d.Staircasing

Apply staircasing scheme to material assignment of Yee grids on structure boundaries.

tidy3d.VolumetricAveraging

Apply volumetric averaging scheme to material properties of Yee grids on structure boundaries.

tidy3d.HeuristicPECStaircasing

Apply a variant of staircasing scheme to PEC boundaries: the electric field grid is set to PEC if the field is substantially parallel to the interface.

tidy3d.PolarizedAveraging

Apply a polarized subpixel averaging method to dielectric boundaries, which is a phenomenological approximation of ContourPathAveraging.

tidy3d.ContourPathAveraging

Apply a contour-path subpixel averaging method to dielectric boundaries.

tidy3d.PECConformal

Apply a subpixel averaging method known as conformal mesh scheme to PEC boundaries.

tidy3d.SurfaceImpedance

Apply 1st order (Leontovich) surface impedance boundary condition to structure made of LossyMetalMedium.

See also

For an introduction to subpixel averaging, please see the following FDTD101 lectures:


Utility Classes#

tidy3d.Coords

Holds data about a set of x,y,z positions on a grid.

tidy3d.FieldGrid

Holds the grid data for a single field.

tidy3d.YeeGrid

Holds the yee grid coordinates for each of the E and H positions.

tidy3d.Grid

Contains all information about the spatial positions of the FDTD grid.

These classes contain information of the grid and related quantities. Advanced users may refer to their respective documentation pages to find specific attributes and methods.