diff --git a/docs/api/boundary_conditions.rst b/docs/api/boundary_conditions.rst index f069992de..52d00d1c0 100644 --- a/docs/api/boundary_conditions.rst +++ b/docs/api/boundary_conditions.rst @@ -3,49 +3,168 @@ Boundary Conditions =================== +Overview +-------- + +In numerical simulations, the simulation domain is necessarily truncated compared to physical reality due to computational limits. Boundary conditions specify the constraints on the field solution along the external boundaries of the simulation domain. In order to achieve good agreement with the physical scenario, it is important that the user specifies the appropriate boundary type for their application. + +The `Boundary Specification`_ section discusses how to set up simulation boundaries in a Tidy3D simulation. + +Each boundary type is discussed in their respective section. The currently supported types are: + ++ `PEC/PMC`_: Simulates a perfect electric or magnetic conductor ++ `Periodic`_: Simulates periodic boundary conditions in 1, 2, or 3-dimensions ++ `Absorbing`_: Simulates an open boundary for outgoing radiation + +~~~~ + +Boundary Specification +---------------------- + .. autosummary:: :toctree: _autosummary/ :template: module.rst tidy3d.BoundarySpec tidy3d.Boundary - tidy3d.BoundaryEdge +The ``BoundarySpec`` object contains information on the boundary conditions on all six sides of the simulation domain. The ``Boundary`` object specifies the boundary conditions along a single axis, i.e. x, y, or z. Typically, the ``Simulation`` object contains a ``BoundarySpec`` instance, which in turn contains three ``Boundary`` instances. + +There are several ways to specify boundaries with ``BoundarySpec``. To quickly specify a single boundary type for all six sides, use the ``BoundarySpec.all_sides()`` method. + +.. code-block:: + + my_boundary_spec = BoundarySpec.all_sides(boundary=PML()) + +To specify boundaries along each of the three axes: + +.. code-block:: + + my_boundary_spec = BoundarySpec( + x = Boundary.periodic(), + y = Boundary.pec(), + z = Boundary.pml(), + ) + +In the above example, built-in convenience methods such as ``pec()``, ``pml()``, and ``periodic()`` in the ``Boundary`` object were used to specify boundaries for both sides of each axis. + +Finally, for full control of each of the six sides: -Types of Boundaries -------------------- +.. code-block:: + + my_boundary_spec = BoundarySpec( + x = Boundary(plus=PECBoundary(), minus=PMCBoundary()), + y = Boundary(plus=Periodic(), minus=Periodic()), + z = Boundary(plus=PML(), minus=PECBoundary()), + ) + +In the above example, individual boundary instances were created and passed into the ``plus`` and ``minus`` attributes of each ``Boundary`` instance. + +.. seealso:: + + For more details and examples, please see the following article: + + + `Setting up boundary conditions <../notebooks/BoundaryConditions.html>`_ + +~~~~ + +PEC/PMC +------- .. autosummary:: :toctree: _autosummary/ :template: module.rst - tidy3d.Periodic tidy3d.PECBoundary tidy3d.PMCBoundary - tidy3d.BlochBoundary + tidy3d.Boundary.pec + tidy3d.Boundary.pmc + +These boundary conditions simulate a perfect electric or magnetic conductor by placing constraints on the normal and tangential components of the electric/magnetic fields. + +.. math:: + + \mathbf{E} \times \mathbf{n} &= 0 \quad \text{(PEC)},\\ + \mathbf{H} \times \mathbf{n} &= 0 \quad \text{(PMC)}. +where :math:`\mathbf{n}` is the boundary normal vector. -Absorbing Boundaries ---------------------- +.. note:: + To simulate a PEC structure, use the ``PECMedium`` class instead. Please refer to the `EM Mediums page `_ for details. -Types of Absorbers -^^^^^^^^^^^^^^^^^^^ + +~~~~ + +Periodic +-------- .. autosummary:: :toctree: _autosummary/ :template: module.rst - tidy3d.PML - tidy3d.StablePML - tidy3d.Absorber + tidy3d.Periodic + tidy3d.BlochBoundary + tidy3d.Boundary.periodic + tidy3d.Boundary.bloch + tidy3d.Boundary.bloch_from_source + +Periodic boundary conditions are commonly used in unit cell simulations. The ``Periodic`` boundary type enforces field continuity, i.e. + +.. math:: + + \mathbf{E}(\mathbf{r}_a) = \mathbf{E}(\mathbf{r}_b) + +where :math:`\mathbf{r}_a` and :math:`\mathbf{r}_b` are matching positions on the respective pair of periodic boundaries. This is commonly used in conjunction with a normal incidence plane wave excitation. + +The ``BlochBoundary`` boundary type implements Bloch periodicity, i.e. + +.. math:: + + \mathbf{E}(\mathbf{r}_a) = e^{i \mathbf{k}_b \cdot (\mathbf{r}_a - \mathbf{r}_b)} \mathbf{E}(\mathbf{r}_b) + +where :math:`\mathbf{k}_b` is the Bloch periodicity vector. This is typically used together with an off-normal incidence plane wave excitation, where the Bloch vector corresponds to the lateral phase difference due to the off-normal plane wave. For user convenience, the ``Boundary.bloch_from_source()`` method automatically creates a ``BlochBoundary`` object from a given excitation. + +.. seealso:: + + For more details and examples, please see the following notebooks: + + + `Multilevel blazed diffraction grating <../notebooks/GratingEfficiency.html>`_ + + `Defining a total-field scattered-field (TFSF) plane wave source <../notebooks/TFSF.html>`_ -Absorber Parameters -^^^^^^^^^^^^^^^^^^^ +~~~~ + +Absorbing +--------- .. autosummary:: :toctree: _autosummary/ :template: module.rst + tidy3d.PML + tidy3d.PMLParams + tidy3d.Boundary.pml + tidy3d.StablePML + tidy3d.Boundary.stable_pml + tidy3d.Absorber + tidy3d.Boundary.absorber tidy3d.AbsorberParams - tidy3d.PMLParams \ No newline at end of file + + +For simulations with radiative modes, it is recommended to surround the simulation domain with absorbing boundary conditions, i.e. either the Perfectly Matched Layer ``PML`` type, or the ``Absorber`` type. + +The ``PML`` boundary type uses coordinate stretching to rapidly attenuate any outgoing radiation, and is the default boundary condition for all simulations in Tidy3D. + +The ``Absorber`` boundary type uses a fictitious lossy medium with ramped conductivity to attenuate outgoing waves. In comparison to the ``PML``, there can be greater reflection at the boundary. The ``Absorber`` boundary is more numerically stable when structures with dispersive mediums extend into the boundary. + +.. seealso:: + + For more details and examples, please see the following article: + + + `Suppressing artificial reflections with absorber and PML boundaries <../notebooks/AbsorbingBoundaryReflection.html>`_ + + For a general introduction to PMLs, please see the following FDTD101 resource: + + + `Introduction to perfectly matched layer (PML) `_ + +~~~~ diff --git a/docs/api/discretization.rst b/docs/api/discretization.rst index f5321c518..de551a200 100644 --- a/docs/api/discretization.rst +++ b/docs/api/discretization.rst @@ -1,7 +1,36 @@ .. currentmodule:: tidy3d -Discretization -============== +Grid Discretization +=================== + +Overview +-------- + +Grid discretization lies at the heart of the FDTD algorithm. The simulation domain is rendered onto a finite grid of spatial points --- including material domains and boundary conditions. From the user's perspective, there are two general categories of length scales to be aware of when it comes to defining the grid: + +* Physical length scales: 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, metallic skin depth etc. + +* Geometric length scales: this refers to the feature sizes of the structure under simulation, such as minimum dimensions, radii of curvature, sharp points etc. + +To obtain good results, the minimum grid size should be small enough to resolve length scales in both of the above categories. + +It is also important to keep in mind the CFL condition, which relates the maximum time step to the minimum grid size in the simulation. When using a very small grid size, the time step will also have to decrease, which can lead to a dramatic increase in simulation cost. Thus, the user should also ensure that they are not using an overly fine grid for their simulation. + +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`_. + + +.. seealso:: + + For an introduction to FDTD discretization and related topics, please see the following FDTD101 lectures: + + + `Introduction to FDTD Simulation `_ + + `Time step size and CFL condition in FDTD `_ + + `Numerical Dispersion in FDTD `_ + +~~~~ + +Grid Specification +------------------ .. autosummary:: :toctree: _autosummary/ @@ -13,10 +42,186 @@ Discretization tidy3d.QuasiUniformGrid tidy3d.CustomGrid tidy3d.CustomGridBoundaries + +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: + +.. code-block:: python + + 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: + +.. code-block:: python + + # 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. + +.. seealso:: + + For more detail explanation and examples, please see the following learning center resources: + + + `Using automatic nonuniform meshing <../notebooks/AutoGrid.html>`_ + +~~~~ + +Refinement +---------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.MeshOverrideStructure + tidy3d.LayerRefinementSpec + tidy3d.GridRefinement + tidy3d.CornerFinderSpec + +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 artifically higher refractive index to enforce higher grid resolution: + +.. code-block:: python + + # fictitous 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: + +.. code-block:: python + + # 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. + +.. code-block:: python + + 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. + +.. seealso:: + + For more detail explanation and examples, please see the following learning center resources: + + + `Using automatic nonuniform meshing: Mesh override structures <../notebooks/AutoGrid.html#Mesh-override-structures>`_ + + `Automatic mesh refinement in layered structures <../notebooks/LayerRefinement.html>`_ + +~~~~ + +Subpixel Averaging +------------------ + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.SubpixelSpec + +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. + +.. code-block:: python + + 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. + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.Staircasing + tidy3d.VolumetricAveraging + tidy3d.HeuristicPECStaircasing + tidy3d.PolarizedAveraging + tidy3d.ContourPathAveraging + tidy3d.PECConformal + tidy3d.SurfaceImpedance + +.. seealso:: + + For an introduction to subpixel averaging, please see the following FDTD101 lectures: + + + `Dielectric constant assignment on Yee grids `_ + + `Introduction to subpixel averaging `_ + +~~~~ + +Utility Classes +--------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + tidy3d.Coords tidy3d.FieldGrid tidy3d.YeeGrid tidy3d.Grid - tidy3d.LayerRefinementSpec - tidy3d.GridRefinement - tidy3d.CornerFinderSpec + +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. + +~~~~ + + + diff --git a/docs/api/geometry.rst b/docs/api/geometry.rst index fc48ed993..a9ab4b314 100644 --- a/docs/api/geometry.rst +++ b/docs/api/geometry.rst @@ -3,6 +3,32 @@ Geometry ======== +Overview +-------- + +Geometry objects are used in Tidy3D to build EM structures. A variety of built-in `primitives`_ are supported, as well as `boolean operations`_ and `spatial transformations`_. Collections of geometry objects can also be combined in `geometry groups`_. + +.. note: + + The default length unit in Tidy3D is the micrometer (:math:`\mu`m). + +Tidy3D also has built-in interoperability with GDSII and STL file formats. See the sections below for details: + ++ `Working with GDS`_ ++ `Working with Trimesh and STL`_ + +.. seealso:: + + For the user's convenience, we have created a list of commonly used photonic crystal and integrated circuit components in the following pages: + + + `Defining common photonic crystal structures <../notebooks/PhotonicCrystalsComponents.html>`_ + + `Defining common integrated photonic components <../notebooks/PICComponents.html>`_ + +~~~~ + +Primitives +---------- + .. autosummary:: :toctree: _autosummary/ :template: module.rst @@ -11,16 +37,245 @@ Geometry tidy3d.Sphere tidy3d.Cylinder tidy3d.PolySlab - tidy3d.TriangleMesh - tidy3d.GeometryGroup + tidy3d.plugins.polyslab.ComplexPolySlab + + +Create 1D lines, 2D planes, and 3D boxes with ``Box``. + +.. code-block:: python + + # create a box by specifying center position and size + my_box1 = Box(center=(-2,0,0), size=(1,2,1)) + + # create a box by specifying min/max bounds + my_box2 = Box.from_bounds(rmin=(-1,-0.5,-1), rmax=(1, 0.5,1 )) + + # create a 2D plane by setting size to zero in the normal direction + my_plane = Box(center=(0,0,-1), size=(5,5,0)) + + # create a 1D line by setting size to zero in two dimensions + my_line = Box(center=(0,3,0), size=(5,0,0)) + + # get the 2D planar faces of a box quickly using the surfaces() method + my_box_surfaces = Box.surfaces(center=(2,0,0), size=(1,1,1)) + my_box_surfaces = my_box_surfaces[4:] # keep only the planes normal to z + +.. figure:: ./img/geom1.png + :width: 480 + :alt: Geometries created with ``Box`` + +Spheres are created with the ``Sphere`` class. The ``Cylinder`` class can be used to create cylinders and conical geometry in 3D, as well as circles in 2D. + +.. code-block:: python + + # create a sphere + my_sphere = Sphere(center=(-2,0,0), radius=1) + + # create a cylinder + my_cylinder = Cylinder(center=(0,0,0), axis=1, radius=0.5, length=2) + + # create a conical geometry by specifying sidewall_angle (radians) + my_conical_shape = Cylinder(center=(2,0,0), axis=2, radius=0.5, length=2, sidewall_angle=np.pi/15) + + # create a circle + my_circle = Cylinder(center=(0,0,-1), axis=2, radius=5, length=0) + +.. figure:: ./img/geom2.png + :width: 480 + :alt: Geometries created with ``Sphere`` and ``Cylinder`` + + +Use the ``PolySlab`` class to create custom polygons in 2D and extruded polygons in 3D. + +.. code-block:: python + + # specify the in-plane polygon vertices + my_vertices = np.array([(-3,0), (-1,0), (-2,1)]) + + # create polyslab from vertices + my_polyslab = PolySlab(vertices=my_vertices, axis=2, slab_bounds=(0,2)) + + # polyslabs can also be tapered using the sidewall_angle attribute + my_vertices2 = np.array([(1, 0), (3, 0), (2.5, 1), (1.5, 1)]) + my_polyslab2 = PolySlab(vertices=my_vertices2, axis=1, slab_bounds=(0,2), sidewall_angle=np.pi/20) + +.. figure:: ./img/geom3.png + :width: 480 + :alt: Geometries created with ``PolySlab`` + +More complicated polyslabs with potentially self-intersecting behavior can be modelled using the ``ComplexPolySlab`` plugin. Please see the linked article below for more information. + +.. seealso:: + + For more details and examples, please see this learning center articles: + + + `Defining self-intersection polygons <../notebooks/SelfIntersectingPolySlab.html>`_ + + `Visualizing geometries in Tidy3D <../notebooks/VizSimulation.html>`_ + +~~~~ + + +Boolean Operations +------------------ + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + tidy3d.ClipOperation + +The ``ClipOperation`` class supports union, intersection, difference, and symmetric difference between two geometry objects. + +.. code-block:: python + + # difference + my_boolean1 = ClipOperation( + operation='difference', + geometry_a=Box(center=(-2,0,0), size=(1,1,2)), + geometry_b=Cylinder(center=(-2,0,0), axis=2, radius=0.25, length=2) + ) + + # intersection + my_boolean2 = ClipOperation( + operation='intersection', + geometry_a=Sphere(center=(2,0,-6), radius=6), + geometry_b=Cylinder(center=(2,0,0), axis=2, radius=2, length=1) + ) + +.. figure:: ./img/geom4.png + :width: 480 + :alt: Geometries created with ``ClipOperation`` + +~~~~ + +Spatial Transformations +----------------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.Geometry.translated + tidy3d.Geometry.scaled + tidy3d.Geometry.rotated tidy3d.Transformed -Transformations ----------------- +You can use ``translated()``, ``scaled()``, and ``rotated()`` with any geometry object to perform the respective transformation. + +.. code-block:: python + + my_box = Box(center=(0,0,0), size=(1,1,2)) + my_box_rotated = my_box.rotated(angle=np.pi/6, axis=1) + my_box_translated = my_box.translated(-2,0,0) + my_box_scaled = my_box.scaled(2,2,0.2) + +.. figure:: ./img/geom5.png + :width: 480 + :alt: Geometry transformations with built-in methods + +Alternatively, you can use the ``Transformed`` class to implement a 4D transformation matrix. + +.. code-block:: python + + # use static methods in Transformed to generate 4D transformation matrices + mat_translation = Transformed.translation(-2, 0, 0) + mat_scaling = Transformed.scaling(1, 0.2, 1) + mat_rotation = Transformed.rotation(angle=np.pi/4, axis=1) + + # multiply matrices together to make arbitrary transformation + mat_transformation = mat_translation @ mat_rotation @ mat_scaling + my_box_transformed = Transformed(geometry=my_box, transform=mat_transformation) + +.. figure:: ./img/geom6.png + :width: 480 + :alt: Geometry transformation with ``Transformed`` + + +.. seealso:: + + For more details and examples, please see the following learning center article: + + + `Geometry transformations <../notebooks/GeometryTransformations.html>`_ + +~~~~ + + +Geometry Groups +--------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.GeometryGroup + +When working with a large number of geometry objects belonging to the same ``tidy3d.Structure``, it is more computationally efficient to combine them into a single ``GeometryGroup``. + +.. code-block:: python + + # create an array of geometry objects + my_geom_list = [] + for i in range(5): + for j in range(5): + my_geom_list += [Box(center=(2*i, 2*j, 0), size=(1,1,1))] + + # consolidate them into a single group to create a single structure + my_geom_group = GeometryGroup(geometries=my_geom_list) + my_structure = Structure(geometry=my_geom_group, medium=my_medium) + + +~~~~ + +Working with GDS +------------------- .. autosummary:: :toctree: _autosummary/ :template: module.rst - tidy3d.RotationAroundAxis + tidy3d.Geometry.from_gds + tidy3d.Geometry.to_gds_file + tidy3d.Geometry.to_gds + tidy3d.Geometry.to_gdstk + tidy3d.Geometry.to_gdspy + +The GDSII file format is commonly used in integration circuit design to specify geometric shapes, labels, and other simulation metadata. Tidy3D supports the creation, import, and export of GDSII files via the third party packages ``gdstk`` or ``gdspy``. Please find detailed usage instructions in the linked articles below. + +.. seealso:: + + For more details and examples, please see the following learning center articles: + + + `Importing GDS files <../notebooks/GDSImport.html>`_ + + `Export to GDS file <../notebooks/GDSExport.html>`_ + +~~~~ + +Working with Trimesh and STL +---------------------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.TriangleMesh + +The ``TriangleMesh`` class is an alternative way to represent geometry using vertex and face information, similar to the STL file format. + +.. code-block:: python + + import trimesh + vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]]) + faces = np.array([[1, 2, 3], [0, 3, 2], [0, 1, 3], [0, 2, 1]]) + my_trimesh_geom = TriangleMesh.from_vertices_faces(vertices, faces) + +Use the ``from_stl()`` class method to import from an external STL file, or ``from_trimesh()`` to import from a ``trimesh.Trimesh`` object. For more information, please see the articles linked below. + +.. seealso:: + + For more details and examples, please see the following learning center articles: + + + `Importing STL files <../notebooks/STLImport.html>`_ + + `Defining complex geometries using trimesh <../notebooks/CreatingGeometryUsingTrimesh.html>`_ + +~~~~ + diff --git a/docs/api/img/geom1.png b/docs/api/img/geom1.png new file mode 100644 index 000000000..a0eb3add5 Binary files /dev/null and b/docs/api/img/geom1.png differ diff --git a/docs/api/img/geom2.png b/docs/api/img/geom2.png new file mode 100644 index 000000000..292a7b1cb Binary files /dev/null and b/docs/api/img/geom2.png differ diff --git a/docs/api/img/geom3.png b/docs/api/img/geom3.png new file mode 100644 index 000000000..61dc4fb78 Binary files /dev/null and b/docs/api/img/geom3.png differ diff --git a/docs/api/img/geom4.png b/docs/api/img/geom4.png new file mode 100644 index 000000000..d56a051d8 Binary files /dev/null and b/docs/api/img/geom4.png differ diff --git a/docs/api/img/geom5.png b/docs/api/img/geom5.png new file mode 100644 index 000000000..8a70a574a Binary files /dev/null and b/docs/api/img/geom5.png differ diff --git a/docs/api/img/geom6.png b/docs/api/img/geom6.png new file mode 100644 index 000000000..0bf016ed5 Binary files /dev/null and b/docs/api/img/geom6.png differ diff --git a/docs/api/index.rst b/docs/api/index.rst index 9001b0574..3c2a58901 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -6,20 +6,18 @@ API |:computer:| :hidden: simulation - boundary_conditions geometry mediums + structures material_library rf_material_library - structures + boundary_conditions + discretization sources analytic_beams monitors - mode field_projector lumped_elements - discretization - subpixel_averaging output_data scene logging @@ -35,22 +33,20 @@ API |:computer:| abstract_models .. include:: /api/simulation.rst -.. include:: /api/boundary_conditions.rst +.. include:: /api/submit_simulations.rst .. include:: /api/geometry.rst .. include:: /api/mediums.rst .. include:: /api/structures.rst +.. include:: /api/scene.rst +.. include:: /api/boundary_conditions.rst +.. include:: /api/discretization.rst .. include:: /api/sources.rst -.. include:: /api/analytic_beams.rst .. include:: /api/monitors.rst -.. include:: /api/mode.rst +.. include:: /api/output_data.rst +.. include:: /api/analytic_beams.rst .. include:: /api/field_projector.rst .. include:: /api/lumped_elements.rst -.. include:: /api/discretization.rst -.. include:: /api/subpixel_averaging.rst -.. include:: /api/output_data.rst -.. include:: /api/scene.rst .. include:: /api/logging.rst -.. include:: /api/submit_simulations.rst .. include:: /api/heat/index.rst .. include:: /api/charge/index.rst .. include:: /api/eme/index.rst @@ -58,4 +54,4 @@ API |:computer:| .. include:: /api/plugins/index.rst .. include:: /api/constants.rst .. include:: /api/abstract_base.rst -.. include:: /api/abstract_models.rst \ No newline at end of file +.. include:: /api/abstract_models.rst diff --git a/docs/api/mediums.rst b/docs/api/mediums.rst index 8f64a67f2..2b2ed6952 100644 --- a/docs/api/mediums.rst +++ b/docs/api/mediums.rst @@ -4,56 +4,247 @@ EM Mediums ========== -Non-Dispersive Medium ---------------------- +Overview +-------- + +The EM medium describes the electromagnetic properties of the material. In conjunction with Maxwell's equations and the constitutive equations, these properties determine how EM waves propagate through and interact with the medium. Tidy3D supports a diverse set of medium types to model various material characteristics. + +In the Tidy3D python API, medium classes are split into six broad categories: + ++ `Non-dispersive`_ medium: Constant relative permittivity :math:`\varepsilon_r` and conductivity :math:`\sigma` ++ `Dispersive`_ medium: Optical property varies with frequency ++ `Anisotropic`_ medium: Optical property varies with direction of light propagation ++ `Spatially-varying`_ medium: Optical property varies with spatial coordinates ++ `Perturbation`_ medium: Optical property is perturbed by the result of a multiphysics (heat/charge) simulation ++ `Metallic`_: Metals in the shallow skin depth regime + +Combinations are possible, e.g. a spatially-varying, dispersive, anisotropic medium. In addition to these categories, users can define additional modifiers on some mediums using medium specifications: + ++ `Nonlinearity`_: Optical property depends on electric field ++ `Spatio-temporal modulation`_: Optical property is modulated by a function of time and spatial coordinates + +The material library also provides a growing list of commonly used material models. + ++ `Material Library `_ ++ `RF Material Library `_ + +~~~~ + +Non-Dispersive +-------------- -Spatially uniform -^^^^^^^^^^^^^^^^^ .. autosummary:: :toctree: _autosummary/ :template: module.rst tidy3d.Medium - tidy3d.LossyMetalMedium - tidy3d.PECMedium - tidy3d.FullyAnisotropicMedium -Spatially varying -^^^^^^^^^^^^^^^^^ +A simple, non-dispersive optical medium can be described by constant relative permittivity :math:`\varepsilon_r` and conductivity :math:`\sigma` (units: S/um). Alternatively, it can also be defined using the real (:math:`n`) and imaginary (:math:`k`) components of the refractive index, but note that this is exact only at a single specified frequency (units: Hz). Thus the latter option is only appropriate for narrow-band simulations. + +.. code-block:: python + + # A lossless medium with constant permittivity + my_lossless_medium = Medium(permittivity=3.8) + + # A lossy medium with constant permittivity and conductivity + my_lossy_medium = Medium(permittivity=4.0, conductivity=1.0) + + # Alternatively, use refractive index n and k at a specified frequency + my_medium_nk = Medium.from_nk(n=1.5, k=1e-3, freq=150e12) + +.. note:: + + To specify a constant :math:`n` and :math:`k` over a wide frequency range, it is required to use a dispersive model. Please see the section on `dispersive`_ mediums. + +.. note:: + + To specify a lossy dielectric using a constant loss tangent model, it is required to use a dispersive model. Please see the section on `dispersive`_ mediums. + +~~~~ + +Dispersive +---------- + .. autosummary:: :toctree: _autosummary/ :template: module.rst - tidy3d.CustomMedium + tidy3d.PoleResidue + tidy3d.Lorentz + tidy3d.Sellmeier + tidy3d.Drude + tidy3d.Debye -Lossy Metal parameters -^^^^^^^^^^^^^^^^^^^^^^ +There are many different models that can be used to describe dispersive mediums. For detailed usage instructions, please visit their respective documentation page. .. autosummary:: :toctree: _autosummary/ :template: module.rst - tidy3d.SurfaceImpedanceFitterParam - tidy3d.HammerstadSurfaceRoughness - tidy3d.HuraySurfaceRoughness + tidy3d.plugins.dispersion.FastDispersionFitter + +Alternatively, the ``FastDispersionFitter`` plugin can be used to generate a dispersive medium from external data. The data can be provided as a local text file or a web URL from the materials database `refractiveindex.info `_. + +.. code-block:: python + + # importing from a local file + my_imported_medium = FastDispersionFitter.from_file("path/to/file.csv", skiprows=1, delimited=",") + + # importing from a URL + my_imported_medium_fromurl = FastDispersionFitter.from_url( + url_file="https://refractiveindex.info/data_csv.php?datafile=database/data-nk/main/Ag/Johnson.yml", + delimiter=",", + ) + +To define a material with constant loss tangent, use the ``constant_loss_tangent_model()`` method. + +.. code-block:: python -Dispersive Mediums ------------------- + # constant loss tangent + my_losstan_medium = FastDispersionFitter.constant_loss_tangent_model( + eps_real=2.2, + loss_tangent=5e-4, + frequency_range=(1e9, 5e9) + ) + +Use the convenience methods ``plot()`` and ``eps_model()`` to access the optical properties of the dispersive material model. + +.. code-block:: python + + # plotting within applicable frequency range + my_freqs = np.linspace(3e14, 5e14, 201) + _ = my_dispersive_medium.plot(freqs=my_freqs) + + # evaluate complex-valued permittivity at a frequency point + eps = my_dispersive_medium.eps_model(3e14) + +.. seealso:: + + For more in-depth discussion and examples, please see the following learning center articles: + + + `Modeling dispersive materials <../notebooks/Dispersion.html>`_ + + `Fitting dispersive material models <../notebooks/Fitting.html>`_ + + For a background introduction to modeling dispersive materials in FDTD, please see the following FDTD101 resource: + + + `Modeling dispersive material in FDTD `_ + +~~~~ + +Anisotropic +----------- -Spatially uniform -^^^^^^^^^^^^^^^^^ .. autosummary:: :toctree: _autosummary/ :template: module.rst - tidy3d.PoleResidue - tidy3d.Lorentz - tidy3d.Sellmeier - tidy3d.Drude - tidy3d.Debye + tidy3d.AnisotropicMedium + tidy3d.FullyAnisotropicMedium + tidy3d.Medium2D + +An anisotropic medium has different optical properties depending on the direction of light propagation. Its relative permittivity is thus specified in the form of a 3x3 tensor. For diagonally anisotropic mediums, use ``AnisotropicMedium``: + +.. code-block:: python + + # specify mediums for the xx, yy, zz diagonal components + medium_xx = Medium(permittivity=4.0) + medium_yy = Medium(permittivity=4.1) + medium_zz = Medium(permittivity=3.9) + my_anisotropic_medium = AnisotropicMedium(xx=medium_xx, yy=medium_yy, zz=medium_zz) + +Note that ``xx``, ``yy``, and ``zz`` can support dispersive mediums as well. To specify all 9 components of the tensor, use ``FullyAnistropicMedium``: + +.. code-block:: python + + # specify the full 3x3 tensor + perm = [[2, 0, 0], [0, 1, 0], [0, 0, 3]] + cond = [[0.1, 0, 0], [0, 0, 0], [0, 0, 0]] + my_anisotropic_medium = FullyAnisotropicMedium(permittivity=perm, conductivity=cond) + +Currently, ``FullyAnisotropicMedium`` only supports non-dispersive mediums. + +The ``Medium2D`` class is used to simulate 2D materials without an out-of-plane response. + +.. seealso:: + + For more in-depth discussion with examples, please see the following learning center articles: + + + `Defining fully anisotropic materials <../notebooks/FullyAnisotropic.html>`_ + + `Defining gyrotropic materials <../notebooks/Gyrotropic.html>`_ + + Example applications: + + + `TFLN Adiabatic Waveguide Coupler <../notebooks/AdiabaticCouplerLN.html>`_ + + `TFLN Polarization Splitter/Rotator <../notebooks/LNOIPolarizationSplitterRotator.html>`_ + + `Hyperbolic Polaritons in Nanostructured hBN <../notebooks/NanostructuredBoronNitride.html>`_ + +~~~~ + +Metallic +-------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.PECMedium + tidy3d.LossyMetalMedium + +At lower frequencies, the EM field typically does not penetrate very far into the metallic medium. In this regime, metallic structures are commonly modeled as boundary conditions. In Tidy3D, a metallic medium is assigned to a structure and the corresponding boundary conditions are automatically applied to its geometric boundaries. + +.. code-block:: python + + # lossless metal + my_pec = PECMedium() + + # lossy metal + my_lossy_metal = LossyMetalMedium(conductivity=58, freq_range=(1e9, 10e9)) + +The ``LossyMetalMedium`` class implements the surface impedance boundary condition (SIBC). It can also accept surface roughness specifications using the Hammerstad or Huray models. Please refer to its documentation page for details. + +.. note:: + + For lossy metallic mediums, always be sure to check the skin depth --- if the skin depth is not negligible compared to the structure size, then ``LossyMetalMedium`` may be not accurate. In that case, use a regular dispersive medium instead. + +~~~~ + +.. _Spatially-varying: + +Spatial Variation +----------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.SpatialDataArray + tidy3d.CustomMedium + +The ``CustomMedium`` class is used to define a spatially-varying non-dispersive medium. The spatial distribution of the optical property is defined using the ``SpatialDataArray`` class. Below, we define an example spherical profile :math:`n(r) = \sqrt(2-(r/R)^2)` as in a Luneburg lens: + +.. code-block:: python + + # spatial grid + R = 20 + Nx, Ny, Nz = 100, 100, 100 + X = np.linspace(-R, R, Nx) + Y = np.linspace(-R, R, Ny) + Z = np.linspace(-R, R, Nz) + Xg, Yg, Zg = np.meshgrid(X, Y, Z, indexing='ij') + rg = np.sqrt(Xg**2 + Yg**2 + Zg**2) + + # n profile + n_profile = np.ones((Nx, Ny, Nz)) + n_profile[rg <= R] = np.sqrt(2-(rg[rg<=R]/R)**2) + + # define SpatialDataArray + n_data = SpatialDataArray(n_profile, coords=dict(x=X, y=Y, z=Z)) + + # define CustomMedium + my_custom_medium = CustomMedium.from_nk(n_data) + +Analogous classes also exist for spatially-varying dispersive and anisotropic mediums. -Spatially varying -^^^^^^^^^^^^^^^^^ .. autosummary:: :toctree: _autosummary/ :template: module.rst @@ -63,10 +254,24 @@ Spatially varying tidy3d.CustomSellmeier tidy3d.CustomDrude tidy3d.CustomDebye + tidy3d.CustomAnisotropicMedium + +.. seealso:: + + For in-depth discussion with examples, see the following learning center article: + + + `Defining spatially-varying dielectric structures <../notebooks/CustomMediumTutorial.html>`_ + + Example applications: + + + `3D Optical Luneburg Lens <../notebooks/OpticalLuneburgLens.html>`_ +~~~~ -Medium Perturbations --------------------- +.. _Perturbation: + +Perturbation (Multiphysics) +--------------------------- .. autosummary:: :toctree: _autosummary/ @@ -75,33 +280,39 @@ Medium Perturbations tidy3d.PerturbationMedium tidy3d.PerturbationPoleResidue +When performing a multiphysics simulation, the temperature or carrier density field will result in a perturbation to the optical medium. -General Mediums (can be both dispersive and non-dispersive) ------------------------------------------------------------ +.. code-block:: python -Spatially uniform -^^^^^^^^^^^^^^^^^ + # define a linear heat perturbation + my_linear_heat_perturbation = LinearHeatPerturbation(coeff=1e-5, temperature_ref = 300) -.. autosummary:: - :toctree: _autosummary/ - :template: module.rst + # define perturbation medium + my_perturbed_medium = PerturbationMedium( + permittivity = 2.0, + permittivity_perturbation = ParameterPerturbation(heat=my_linear_heat_perturbation) + ) - tidy3d.AnisotropicMedium - tidy3d.Medium2D +Multiphysics simulations require additional set up in addition to defining a perturbation medium. To get started, we recommend that you check out the example models listed below. -Spatially varying -^^^^^^^^^^^^^^^^^ -.. autosummary:: - :toctree: _autosummary/ - :template: module.rst +.. seealso:: - tidy3d.CustomAnisotropicMedium + Example applications (thermal): + + + `Thermally Tuned Ring Resonator <../notebooks/ThermallyTunedRingResonator.html>`_ + + `Thermally Tuned Waveguide <../notebooks/MetalHeaterPhaseShifter.html>`_ + + Example applications (charge): + + + `Carrier Injection Based Mach-Zehnder Modulator <../notebooks/MachZehnderModulator.html>`_ + + `Thermo-optic Modulator with a Doped Silicon Heater <../notebooks/ThermoOpticDopedModulator.html>`_ -Medium Specifications (add properties to existing Medium) ---------------------------------------------------------- -Nonlinear -^^^^^^^^^ +~~~~ + + +Nonlinearity +------------ .. autosummary:: :toctree: _autosummary/ @@ -112,8 +323,36 @@ Nonlinear tidy3d.KerrNonlinearity tidy3d.TwoPhotonAbsorption -Time Modulation -^^^^^^^^^^^^^^^ +Nonlinear mediums are modeled as regular mediums with an added `NonlinearSpec` specification. + +.. code-block:: python + + # firstly, define a nonlinear model of interest + my_nonlinear_model = NonlinearSusceptibility(chi3=1.0) + + # then, define the nonlinear spec + my_nonlinear_spec = NonlinearSpec(models=[my_nonlinear_model], num_iters=5) + + # finally, define the nonlinear medium + my_nonlinear_medium = Medium(permittivity=2.0, nonlinear_spec=my_nonlinear_spec) + +Nonlinear problems are solved iteratively; use the ``num_iters`` parameter in ``NonlinearSpec`` to control the number of iterations. Currently, three nonlinear models are supported, ``NonlinearSusceptibility``, ``KerrNonlinearity``, and ``TwoPhotonAbsorption``. For details, please refer to the corresponding reference article. + +.. note:: + + Nonlinear simulations are generally quite complex and the proper approach can vary greatly on a case-by-case basis. Other than defining a nonlinear medium, additional simulation subtleties are likely present when compared to their linear counterparts. + +.. seealso:: + + Example applications: + + + `Generation of Kerr Sideband <../notebooks/KerrSidebands.html>`_ + + `Bistability in Photonic Crystal Microcavities <../notebooks/BistablePCCavity.html>`_ + +~~~~ + +Spatio-temporal Modulation +-------------------------- .. autosummary:: :toctree: _autosummary/ @@ -123,32 +362,31 @@ Time Modulation tidy3d.ContinuousWaveTimeModulation tidy3d.SpaceModulation -Material Library ----------------- +In active nanophotonic devices, the medium can be modulated both spatially and temporally. The ``ModulationSpec`` class allows the user to specify such modulations. This modulation is then passed as a parameter into one of the standard medium classes. -.. toctree:: - material_library - rf_material_library +.. code-block:: python + # define time modulation + my_time_modulation = ContinuousWaveTimeModulation(freq0=1e12, amplitude=0.1, phase=0) -Abstract Classes ------------------ - -.. autosummary:: - :toctree: _autosummary/ + # define spatial modulation + my_spatial_modulation = SpaceModulation(amplitude=1.0, phase=0) - tidy3d.components.medium.AbstractPerturbationMedium - tidy3d.components.medium.NonlinearModel + # define space-time modulation + my_spacetime_modulation = SpaceTimeModulation(time_modulation=my_time_modulation, space_modulation=my_spatial_modulation) + # define modulation spec + my_modulation_spec = ModulationSpec(permittivity=my_spacetime_modulation, conductivity=None) -Multi-Physics Medium -==================== + # define modulated material + my_modulated_medium = Medium(permittivity=2.0, modulation_spec=my_modulation_spec) +In the example above, the ``ContinuousWaveTimeModulation`` specifies a time-harmonic modulation with frequency, amplitude and phase given by the respective parameters. The ``SpaceModulation`` with ``amplitude=1.0`` results in no spatial modulation. The two modulation factors are multiplied together, and the result is added to the unmodulated permittivity value. In the modulated medium, the permittivity now varies between ``1.9`` and ``2.1``. -.. autosummary:: - :toctree: _autosummary/ +.. seealso:: - tidy3d.components.material.multi_physics.MultiPhysicsMedium + For in-depth discussion with examples, see the following learning center article: + + `Applying time modulation to materials <../notebooks/TimeModulationTutorial.html>`_ diff --git a/docs/api/monitors.rst b/docs/api/monitors.rst index 861351d98..116928703 100644 --- a/docs/api/monitors.rst +++ b/docs/api/monitors.rst @@ -4,8 +4,32 @@ Monitors ======== -Monitor Types -------------- +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 +* `Diffraction`_: Records diffraction coefficient(s) in a periodic simulation +* `Far-field`_: Various monitors for calculating far-field projection and radiation characteristics +* `Permittivity`_: Records material properties within a given region + +.. seealso:: + + To learn more about accessing and plotting monitor data, please refer to the following learning center articles: + + + `Performing visualization of simulation data <../notebooks/VizData.html>`_ + + `Advanced monitor data (xarray) manipulation and visualization <../notebooks/XarrayTutorial.html>`_ + + `Creating FDTD animations <../notebooks/AnimationTutorial.html>`_ + +~~~~ + +Field +----- .. autosummary:: :toctree: _autosummary/ @@ -13,22 +37,190 @@ Monitor Types tidy3d.FieldMonitor tidy3d.FieldTimeMonitor + +The ``FieldMonitor`` records the EM field components within a spatial region at specified frequency point(s). The ``FieldTimeMonitor`` does the same, except at specified time intervals instead of frequency. + +.. code-block:: python + + # 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 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 +---- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + tidy3d.FluxMonitor tidy3d.FluxTimeMonitor + +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. + +.. code-block:: python + + # 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 times between each measurement + ) + +.. seealso:: + + Example applications: + + + `Scattering of a plasmonic nanoparticle <../notebooks/PlasmonicNanoparticle.html>`_ + + `Plasmonic Yagi-Uda nanoantenna <../notebooks/PlasmonicYagiUdaNanoantenna.html>`_ + +~~~~ + +Mode +---- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.ModeSpec tidy3d.ModeMonitor tidy3d.ModeSolverMonitor - tidy3d.PermittivityMonitor + +The ``ModeMonitor`` records the mode coefficients of the incident field at specified frequency point(s). + +Behind the scene, 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. + +.. code-block:: python + + # 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, + ) + +.. seealso:: + + For more details and examples, please refer to the following learning center article: + + + `Defining mode sources and monitors <../notebooks/ModalSourcesMonitors>`_ + + Example applications: + + + `Waveguide Y-junction <../notebooks/YJunction.html>`_ + + `Broadband directional coupler <../notebooks/BroadbandDirectionalCoupler.html>`_ + +~~~~ + +Diffraction +----------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.DiffractionMonitor + +The ``DiffractionMonitor`` records the diffraction coefficients of the allowed diffraction orders in a periodic simulation. + +.. code-block:: + + # 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. + +.. seealso:: + + Example applications: + + + `Multilevel blazed diffraction grating <../notebooks/GratingEfficiency.html>`_ + + `Mid-IR metalens based on silicon nanopillars <../notebooks/MidIRMetalens.html>`_ + +~~~~ + +Far-field +--------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + tidy3d.FieldProjectionCartesianMonitor tidy3d.FieldProjectionAngleMonitor tidy3d.FieldProjectionKSpaceMonitor - tidy3d.DiffractionMonitor tidy3d.DirectivityMonitor -Apodization Specification -------------------------- +.. seealso:: + + For more details and examples, please refer to the following learning center article: + + + `Performing near field to far field projections <../notebooks/FieldProjections.html>`_ + +~~~~ + +Permittivity +------------ + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.PermittivityMonitor + +~~~~ + +Apodization +----------- .. autosummary:: :toctree: _autosummary/ :template: module.rst tidy3d.ApodizationSpec + +~~~~ diff --git a/docs/api/sources.rst b/docs/api/sources.rst index a6139e2c6..3cb013a8e 100644 --- a/docs/api/sources.rst +++ b/docs/api/sources.rst @@ -3,9 +3,68 @@ Sources ======= +Overview +-------- -Types of Sources ----------------- +Sources in Tidy3D provide the necessary excitation to investigate the EM behaviour of the structures under simulation. The type of source used in a simulation tends to very application-specific. For instance, a ``PlaneWave`` source may be used for a unit cell simulation in a metalens; whereas a ``ModeSource`` would be more appropriate for a waveguide crossing problem. + +A generic source can be thought of as composed of two parts: a spatial profile and a temporal profile. The former dictates the field distribution in space, whereas the latter determines the frequency band covered by the source, and by extension, the overall simulation. + +The following section describes how to specify source time-dependence: + +* `Source Time Dependence`_ + +The following sections describe the available spatial source distributions in Tidy3D: + +* `Dipole and Uniform Current`_ +* `Plane Wave`_ +* `Gaussian Beam`_ +* `Mode Source`_ +* `Total-Field/Scattered-Field (TFSF)`_ +* `User-defined`_ + +~~~~ + +Source Time Dependence +---------------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.GaussianPulse + tidy3d.ContinuousWave + tidy3d.CustomSourceTime + +Each source requires the ``source_time`` parameter to be defined, which provides the time-dependence of the source. + +.. code-block:: python + + # frequency information + my_center_frequency = 200e12 # center frequency in Hz + my_bandwidth = 20e12 # bandwidth + + # my source time + my_source_time = GaussianPulse( + freq0=my_center_frequency, + fwidth=my_bandwidth + ) + + # a point dipole source + my_dipole_source = PointDipole( + center=(0,0,0), + source_time=my_source_time, + polarization='Ex' + ) + +In the example above, we defined a ``PointDipole`` source with a modulated Gaussian pulse time-dependence. This is well-suited for simulations with a specified center frequency and bandwidth, and thus is by far the most common type of time-dependence used. + +For niche applications, the user may wish to define a ``ContinuousWave`` excitation or even a ``CustomSourceTime`` function. Please refer to their respective documentation page for more details. + +~~~~ + +Dipole and Uniform Current +-------------------------- .. autosummary:: :toctree: _autosummary/ @@ -13,33 +72,200 @@ Types of Sources tidy3d.PointDipole tidy3d.UniformCurrentSource + +The ``PointDipole`` represents an infinitesimally small isotropic radiator. + +.. code-block:: python + + my_point_dipole = PointDipole( + center=(0,0,0), + source_time=my_source_time, + polarization='Ex' + ) + +The ``UniformCurrentSource`` represents a 1D line, 2D sheet, or 3D box of uniform current. + +.. code-block:: python + + # define a 2D sheet of current polarized in the z-direction + my_uniform_current_source = UniformCurrentSource( + center=(0,0,0), + size=(1,0,1), + source_time=my_source_time, + polarization='Ez' + ) + +.. seealso:: + + Example applications: + + * `Band structure calculation of a photonic crystal slab <../notebooks/Bandstructure.html>`_ + * `Nanobeam cavity <../notebooks/NanobeamCavity.html>`_ + +~~~~ + +Plane Wave +---------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + tidy3d.PlaneWave - tidy3d.ModeSource + +The ``PlaneWave`` class represents an incident plane wave of a certain polarization and orientation. This is typically used in conjunction with periodic boundary conditions, e.g. in a unit cell simulation. + +.. code-block:: python + + # define a x-polarized plane wave travelling at a 45 degree angle + # from the positive z-axis + my_plane_wave_source = PlaneWave( + center=(0,0,-1), + size=(td.inf, td.inf, 0), # extend source to simulation edge + source_time=my_source_time, + direction='+', + angle_theta=np.pi/4, + pol_angle=0, + ) + +.. seealso:: + + For more detailed explanation and examples, please see the following learning center resources: + + + `Broadband plane wave with a constant oblique incident angle <../notebooks/BroadbandPlaneWaveWithConstantObliqueIncidentAngle.html>`_ + + Example applications: + + * `Dielectric metasurface absorber <../notebooks/DielectricMetasurfaceAbsorber.html>`_ + * `Mid-IR metalens based on silicon nanopillars <../notebooks/MidIRMetalens.html>`_ + + +~~~~ + +Gaussian Beam +------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + tidy3d.GaussianBeam tidy3d.AstigmaticGaussianBeam - tidy3d.CustomFieldSource - tidy3d.CustomCurrentSource - tidy3d.TFSF +The ``GaussianBeam`` and ``AstigmaticGaussianBeam`` classes implement the paraxial form of the Gaussian beam. -Source Time Dependence ----------------------- +.. code-block:: python + + # define a y-polarized gaussian beam propagating in the +x direction + # with waist radius = 3 um + my_gaussian_beam = GaussianBeam( + size=(0,10,10), # size of the source plane + direction='+', + source_time=my_source_time, + pol_angle=0, + waist_radius=3, + waist_distance=5, + ) + +.. note:: + + The paraxial approximation to the Gaussian beam is only appropriate when the ``waist_radius`` is larger than the source wavelength. + + +.. seealso:: + + Example applications: + + * `Inverse taper edge coupler <../notebooks/EdgeCoupler.html>`_ + * `Uniform grating coupler <../notebooks/GratingCoupler.html>`_ + +~~~~ + +Mode Source +----------- .. autosummary:: :toctree: _autosummary/ :template: module.rst - tidy3d.GaussianPulse - tidy3d.ContinuousWave - tidy3d.CustomSourceTime + tidy3d.ModeSource + tidy3d.ModeSpec + +The ``ModeSource`` class represents a propagating mode in a given structure cross section. + +Behind the scenes, the desired mode is initially obtained by running the mode solver on the ``ModeSource`` plane. The ``ModeSpec`` class provides the settings for the mode solver. Once the desired mode is found, it is injected into the 3D simulation along the plane normal. The user does not need to evoke the mode solver explicitly; it is performed automatically whenever a ``ModeSource`` or ``ModeMonitor`` is included in a Tidy3D simulation. + +.. code-block:: python + + # custom mode specification tells the mode solver to search for + # two modes around effective index = 1.5 + my_mode_spec = ModeSpec(num_modes=2, target_neff=1.5) + + # custom mode source injects the first mode along the +x direction + my_mode_source = ModeSource( + size=(0,10,10), + source_time=my_source_time, + direction='+', + mode_spec=my_mode_spec, + mode_index=0, + ) + +.. seealso:: + + For more detailed explanation and examples, please see the following learning center resources: + + `Defining mode sources and monitors <../notebooks/ModalSourcesMonitors.html>`_ + + `Injecting modes in bent and angled waveguides <../notebooks/ModeBentAngled.html>`_ -Angled Plane Wave Specifications --------------------------------- + For a short introduction to the use of mode sources, see the following FDTD101 lecture: + + + `Mode injection `_ + +~~~~ + +Total-Field/Scattered-Field (TFSF) +---------------------------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.TFSF + +The ``TFSF`` class represents an incident plane-wave wave source that is confined to a specific TFSF region. This type of source is typically used for scattering simulations. Within the TFSF region, the overall field comprises of the incident plane wave and the scattered field. At the edges of the TFSF region, the incident plane wave field is deliberately cancelled out, such that outside the TFSF region, the total field only contains the scattered field. + +.. seealso:: + + For more detailed explanation and examples, please see the following learning center resource: + + + `Defining a total-field scattered-field (TFSF) plane wave source <../notebooks/TFSF.html>`_ + + Example applications: + + + `Scattering of a plasmonic nanoparticle <../notebooks/PlasmonicNanoparticle.html>`_ + + `Multipole expansion for electromagnetic scattering <../notebooks/MultipoleExpansion.html>`_ + +~~~~ + +User-defined +------------ .. autosummary:: :toctree: _autosummary/ :template: module.rst - tidy3d.FixedInPlaneK - tidy3d.FixedAngle + tidy3d.CustomFieldSource + tidy3d.CustomCurrentSource + +It is possible to define an arbitrary field source in Tidy3D using ``CustomFieldSource`` or ``CustomCurrentSource``. Possible usage scenarios include defining a field profile that is not currently available in Tidy3D, or injecting a source that is based on the output of a previous simulation. + +Please see the learning center article linked below for more details. + +.. seealso:: + + For more detailed explanation and examples, please see the following learning center resource: + + + `Defining spatially-varying sources <../notebooks/CustomFieldSource.html>`_ + +~~~~ +