diff --git a/doc/docs/Python_User_Interface.md b/doc/docs/Python_User_Interface.md index f8725bfc7..e70523756 100644 --- a/doc/docs/Python_User_Interface.md +++ b/doc/docs/Python_User_Interface.md @@ -480,6 +480,23 @@ rounded to single precision. + + +
+ +```python +def timestep(self): +``` + +
+ +Return the number of elapsed timesteps. + +
+ +
+ +
@@ -4688,6 +4705,7 @@ The grid points are defined at the corners of the voxels. ![](images/material_grid.png#center) Elements of the `weights` array must be in the range [0,1] where 0 is `medium1` and 1 is `medium2`. +An array of boolean values `False` and `True` will be converted to 0 and 1, respectively. The `weights` array is used to define a linear interpolation from `medium1` to `medium2`. Two material types are supported: (1) frequency-independent isotropic $\varepsilon$ (`epsilon_diag` and `epsilon_offdiag` are interpolated) and (2) `LorentzianSusceptibility` (`sigma` and `sigma_offdiag` @@ -4699,7 +4717,8 @@ For improving accuracy, [subpixel smoothing](Subpixel_Smoothing.md) can be enabl `do_averaging=True`. If you want to use a material grid to define a (nearly) discontinuous, piecewise-constant material that is *either* `medium1` or `medium2` almost everywhere, you can optionally enable a (smoothed) *projection* feature by setting the parameter `beta` to a -positive value. When the projection feature is enabled, the weights $u(x)$ can be thought of as a +positive value. The default is no projection (`beta=0`). When the projection feature is +enabled, the weights $u(x)$ can be thought of as a [level-set function](https://en.wikipedia.org/wiki/Level-set_method) defining an interface at $u(x)=\eta$ with a smoothing factor $\beta$ where $\beta=+\infty$ gives an unsmoothed, discontinuous interface. The projection operator is $(\tanh(\beta\times\eta) @@ -4708,9 +4727,12 @@ involving the parameters `beta` ($\beta$: bias or "smoothness" of the turn on) a ($\eta$: offset for erosion/dilation). The level set provides a general approach for defining a *discontinuous* function from otherwise continuously varying (via the bilinear interpolation) grid values. Subpixel smoothing is fast and accurate because it exploits an analytic formulation -for level-set functions. Note that when `do_averaging=True`, projection must be set through `beta` -in `MaterialGrid`s instead of as a user-defined preprocessing step of `weights`; on the other hand, -you should have the additional projection (or directly plot $\varepsilon$) to visualize the actual structure. +for level-set functions. Note that when subpixel smoothing is enabled via `do_averaging=True`, +projecting the `weights` is done internally using the `beta` parameter. It is therefore not +necessary to manually project the `weights` outside of `MaterialGrid`. However, visualizing +the `weights` used to define the structure does require manually projecting the `weights` yourself. +(Alternatively, you can output the actual structure using [`plot2D`](#data-visualization) or +[`output_epsilon`](#output-functions_1).) A nonzero `damping` term creates an artificial conductivity $\sigma = u(1-u)*$`damping`, which acts as dissipation loss that penalizes intermediate pixel values of non-binarized structures. The value of @@ -6274,7 +6296,7 @@ def __init__(self, side: int = -1, R_asymptotic: float = 1e-15, mean_stretch: float = 1.0, - pml_profile: Callable[[float], float] = at 0x7f79ed336a70>): + pml_profile: Callable[[float], float] = at 0x7f517cb736d0>): ```
@@ -6687,26 +6709,26 @@ Returns the total power of the fields from the eigenmode source at frequency `fr --- - + -### GaussianBeamSource +### GaussianBeam3DSource ```python -class GaussianBeamSource(Source): +class GaussianBeam3DSource(Source): ```
-This is a subclass of `Source` and has **all of the properties** of `Source` above. However, the `component` parameter of the `Source` object is ignored. The [Gaussian beam](https://en.wikipedia.org/wiki/Gaussian_beam) is a transverse electromagnetic mode for which the source region must be a *line* (in 2d) or *plane* (in 3d). For a beam polarized in the $x$ direction with propagation along $+z$, the electric field is defined by $\mathbf{E}(r,z)=E_0\hat{x}\frac{w_0}{w(z)}\exp\left(\frac{-r^2}{w(z)^2}\right)\exp\left(-i\left(kz + k\frac{r^2}{2R(z)}\right)\right)$ where $r$ is the radial distance from the center axis of the beam, $z$ is the axial distance from the beam's focus (or "waist"), $k=2\pi n/\lambda$ is the wavenumber (for a free-space wavelength $\lambda$ and refractive index $n$ of the homogeneous, lossless medium in which the beam propagates), $E_0$ is the electric field amplitude at the origin, $w(z)$ is the radius at which the field amplitude decays by $1/e$ of its axial values, $w_0$ is the beam waist radius, and $R(z)$ is the radius of curvature of the beam's wavefront at $z$. The only independent parameters that need to be specified are $w_0$, $E_0$, $k$, and the location of the beam focus (i.e., the origin: $r=z=0$). +This is a subclass of `Source` and has **all of the properties** of `Source` above. However, the `component` parameter of the `Source` object is ignored. The [Gaussian beam](https://en.wikipedia.org/wiki/Gaussian_beam) is a transverse electromagnetic mode for which the source region must be a *line* (in 2d) or *plane* (in 3d). For a beam polarized in the $x$ direction with propagation along $+z$, the electric field is defined by $\mathbf{E}(r,z)=E_0\hat{x}\frac{w_0}{w(z)}\exp\left(\frac{-r^2}{w(z)^2}\right)\exp\left(-i\left(kz + k\frac{r^2}{2R(z)}\right)\right)$ where $r$ is the radial distance from the center axis of the beam, $z$ is the axial distance from the beam's focus (or "waist"), $k=2\pi n/\lambda$ is the wavenumber (for a free-space wavelength $\lambda$ and refractive index $n$ of the homogeneous, lossless medium in which the beam propagates), $E_0$ is the electric-field amplitude at the origin, $w(z)$ is the radius at which the field amplitude decays by $1/e$ of its axial values, $w_0$ is the beam waist radius, and $R(z)$ is the radius of curvature of the beam's wavefront at $z$. The only independent parameters that need to be specified are $w_0$, $E_0$, $k$, and the location of the beam focus (i.e., the origin: $r=z=0$). -(In 3d, we use a ["complex point-source" method](https://doi.org/10.1364/JOSAA.16.001381) to define a source that generates an exact Gaussian-beam solution. In 2d, we currently use the simple approximation of taking a cross-section of the 3d beam. In both cases, the beam is most accurate near the source's center frequency.) +In 3d, we use a ["complex point-source" method](https://doi.org/10.1364/JOSAA.16.001381) to define a source that generates an exact Gaussian-beam solution. In 2d, we currently use the simple approximation of taking a cross-section of the 3d beam. In both cases, the beam is most accurate near the source's center frequency.) To use the true solution for a 2d Gaussian beam, use the `GaussianBeam2DSource` class instead. -The `SourceTime` object (`Source.src`), which specifies the time dependence of the source, should normally be a narrow-band `ContinuousSource` or `GaussianSource`. (For a `CustomSource`, the beam frequency is determined by the source's `center_frequency` parameter.) +The `SourceTime` object (`Source.src`), which specifies the time dependence of the source, should normally be a narrow-band `ContinuousSource` or `GaussianSource`. (For a `CustomSource`, the beam frequency is determined by the source's `center_frequency` parameter.
- +
@@ -6740,6 +6762,23 @@ Construct a `GaussianBeamSource`.
+--- + + +### GaussianBeam2DSource + +```python +class GaussianBeam2DSource(GaussianBeam3DSource): +``` + +
+ +Identical to `GaussianBeam3DSource` except that the beam is defined in 2d. +This is useful for 2d simulations where the 3d beam is not exact. + +
+ + --- diff --git a/doc/docs/Python_User_Interface.md.in b/doc/docs/Python_User_Interface.md.in index 53c6f096d..fcf2b1c10 100644 --- a/doc/docs/Python_User_Interface.md.in +++ b/doc/docs/Python_User_Interface.md.in @@ -837,7 +837,9 @@ The following classes are available directly via the `meep` package. @@ EigenModeSource[methods-with-docstrings] @@ -@@ GaussianBeamSource[methods-with-docstrings] @@ +@@ GaussianBeam3DSource[methods-with-docstrings] @@ + +@@ GaussianBeam2DSource @@ @@ ContinuousSource[methods-with-docstrings] @@ diff --git a/python/geom.py b/python/geom.py index 29520e01d..596d7a519 100755 --- a/python/geom.py +++ b/python/geom.py @@ -622,7 +622,8 @@ def __init__( `do_averaging=True`. If you want to use a material grid to define a (nearly) discontinuous, piecewise-constant material that is *either* `medium1` or `medium2` almost everywhere, you can optionally enable a (smoothed) *projection* feature by setting the parameter `beta` to a - positive value. When the projection feature is enabled, the weights $u(x)$ can be thought of as a + positive value. The default is no projection (`beta=0`). When the projection feature is + enabled, the weights $u(x)$ can be thought of as a [level-set function](https://en.wikipedia.org/wiki/Level-set_method) defining an interface at $u(x)=\\eta$ with a smoothing factor $\\beta$ where $\\beta=+\\infty$ gives an unsmoothed, discontinuous interface. The projection operator is $(\\tanh(\\beta\\times\\eta) @@ -631,7 +632,12 @@ def __init__( ($\\eta$: offset for erosion/dilation). The level set provides a general approach for defining a *discontinuous* function from otherwise continuously varying (via the bilinear interpolation) grid values. Subpixel smoothing is fast and accurate because it exploits an analytic formulation - for level-set functions. + for level-set functions. Note that when subpixel smoothing is enabled via `do_averaging=True`, + projecting the `weights` is done internally using the `beta` parameter. It is therefore not + necessary to manually project the `weights` outside of `MaterialGrid`. However, visualizing + the `weights` used to define the structure does require manually projecting the `weights` yourself. + (Alternatively, you can output the actual structure using [`plot2D`](#data-visualization) or + [`output_epsilon`](#output-functions_1).) A nonzero `damping` term creates an artificial conductivity $\\sigma = u(1-u)*$`damping`, which acts as dissipation loss that penalizes intermediate pixel values of non-binarized structures. The value of diff --git a/python/source.py b/python/source.py index a74c84dd7..169f6a9b0 100644 --- a/python/source.py +++ b/python/source.py @@ -676,11 +676,11 @@ def add_source(self, sim): class GaussianBeam3DSource(Source): """ - This is a subclass of `Source` and has **all of the properties** of `Source` above. However, the `component` parameter of the `Source` object is ignored. The [Gaussian beam](https://en.wikipedia.org/wiki/Gaussian_beam) is a transverse electromagnetic mode for which the source region must be a *line* (in 2d) or *plane* (in 3d). For a beam polarized in the $x$ direction with propagation along $+z$, the electric field is defined by $\\mathbf{E}(r,z)=E_0\\hat{x}\\frac{w_0}{w(z)}\\exp\\left(\\frac{-r^2}{w(z)^2}\\right)\\exp\\left(-i\\left(kz + k\\frac{r^2}{2R(z)}\\right)\\right)$ where $r$ is the radial distance from the center axis of the beam, $z$ is the axial distance from the beam's focus (or "waist"), $k=2\\pi n/\\lambda$ is the wavenumber (for a free-space wavelength $\\lambda$ and refractive index $n$ of the homogeneous, lossless medium in which the beam propagates), $E_0$ is the electric field amplitude at the origin, $w(z)$ is the radius at which the field amplitude decays by $1/e$ of its axial values, $w_0$ is the beam waist radius, and $R(z)$ is the radius of curvature of the beam's wavefront at $z$. The only independent parameters that need to be specified are $w_0$, $E_0$, $k$, and the location of the beam focus (i.e., the origin: $r=z=0$). + This is a subclass of `Source` and has **all of the properties** of `Source` above. However, the `component` parameter of the `Source` object is ignored. The [Gaussian beam](https://en.wikipedia.org/wiki/Gaussian_beam) is a transverse electromagnetic mode for which the source region must be a *line* (in 2d) or *plane* (in 3d). For a beam polarized in the $x$ direction with propagation along $+z$, the electric field is defined by $\\mathbf{E}(r,z)=E_0\\hat{x}\\frac{w_0}{w(z)}\\exp\\left(\\frac{-r^2}{w(z)^2}\\right)\\exp\\left(-i\\left(kz + k\\frac{r^2}{2R(z)}\\right)\\right)$ where $r$ is the radial distance from the center axis of the beam, $z$ is the axial distance from the beam's focus (or "waist"), $k=2\\pi n/\\lambda$ is the wavenumber (for a free-space wavelength $\\lambda$ and refractive index $n$ of the homogeneous, lossless medium in which the beam propagates), $E_0$ is the electric-field amplitude at the origin, $w(z)$ is the radius at which the field amplitude decays by $1/e$ of its axial values, $w_0$ is the beam waist radius, and $R(z)$ is the radius of curvature of the beam's wavefront at $z$. The only independent parameters that need to be specified are $w_0$, $E_0$, $k$, and the location of the beam focus (i.e., the origin: $r=z=0$). - (In 3d, we use a ["complex point-source" method](https://doi.org/10.1364/JOSAA.16.001381) to define a source that generates an exact Gaussian-beam solution. In 2d, we currently use the simple approximation of taking a cross-section of the 3d beam. In both cases, the beam is most accurate near the source's center frequency.) To use the true solution for a 2d Gaussian Beam, use the `GaussianBeam2DSource` class instead. + In 3d, we use a ["complex point-source" method](https://doi.org/10.1364/JOSAA.16.001381) to define a source that generates an exact Gaussian-beam solution. In 2d, we currently use the simple approximation of taking a cross-section of the 3d beam. In both cases, the beam is most accurate near the source's center frequency.) To use the true solution for a 2d Gaussian beam, use the `GaussianBeam2DSource` class instead. - The `SourceTime` object (`Source.src`), which specifies the time dependence of the source, should normally be a narrow-band `ContinuousSource` or `GaussianSource`. (For a `CustomSource`, the beam frequency is determined by the source's `center_frequency` parameter.) + The `SourceTime` object (`Source.src`), which specifies the time dependence of the source, should normally be a narrow-band `ContinuousSource` or `GaussianSource`. (For a `CustomSource`, the beam frequency is determined by the source's `center_frequency` parameter. """ def __init__( @@ -798,16 +798,8 @@ def get_equiv_sources(field, normal_vec, time_src, center, size): class GaussianBeam2DSource(GaussianBeam3DSource): """ - Identical to `GaussianBeamSource`, except that the beam is defined in 2d. This is useful for 2d simulations, where the 3d beam is not exact. - - The `SourceTime` object (`Source.src`), which specifies the time dependence of the source, should normally be a narrow-band `ContinuousSource` or `GaussianSource`. (For a `CustomSource`, the beam frequency is determined by the source's `center_frequency` parameter.) - - - self._beam_x0 = beam_x0 - self._beam_kdir = beam_kdir - self._beam_w0 = beam_w0 - self._beam_E0 = beam_E0 - + Identical to `GaussianBeam3DSource` except that the beam is defined in 2d. + This is useful for 2d simulations where the 3d beam is not exact. """ def get_fields(self, sim):