Skip to content

Commit

Permalink
Adding Sellmeier.from_dispersion()
Browse files Browse the repository at this point in the history
  • Loading branch information
momchil-flex committed Feb 2, 2022
1 parent 1dc8cc0 commit 2a13235
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- ``Selmeier.from_dispersion()`` method to quickly make a single-pole fit for lossless weakly dispersive materials.
- Stable dispersive material fits via webservice.
- Validates simulation based on discretized size.

Expand Down
19 changes: 19 additions & 0 deletions tests/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,25 @@ def test_medium_dispersion_create():
struct = Structure(geometry=Box(size=(1, 1, 1)), medium=medium)


def test_sellmeier_from_dispersion():
n = 3.5
wvl = 0.5
freq = C_0 / wvl
dn_dwvl = -0.1
with pytest.raises(ValidationError) as e:
# Check that postivie dispersion raises an error
medium = Sellmeier.from_dispersion(n=n, freq=freq, dn_dwvl=-dn_dwvl)

# Check that medium properties are as epected
medium = Sellmeier.from_dispersion(n=n, freq=freq, dn_dwvl=dn_dwvl)
epses = [medium.eps_model(f) for f in [0.99 * freq, freq, 1.01 * freq]]
ns = np.sqrt(epses)
dn_df = (ns[2] - ns[0]) / 0.02 / freq

assert np.allclose(ns[1], n)
assert np.allclose(-dn_df * C_0 / wvl ** 2, dn_dwvl)


def eps_compare(medium: Medium, expected: Dict, tol: float = 1e-5):

for freq, val in expected.items():
Expand Down
37 changes: 35 additions & 2 deletions tidy3d/components/medium.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .validators import validate_name_str

from ..constants import C_0, pec_val, EPSILON_0, HERTZ, CONDUCTIVITY, PERMITTIVITY, RADPERSEC
from ..log import log
from ..log import log, ValidationError


def ensure_freq_in_range(eps_model: Callable[[float], complex]) -> Callable[[float], complex]:
Expand Down Expand Up @@ -268,7 +268,7 @@ def from_nk(cls, n: float, k: float, freq: float):
Real part of refractive index.
k : float = 0
Imaginary part of refrative index.
frequency : float
freq : float
Frequency to evaluate permittivity at (Hz).
Returns
Expand Down Expand Up @@ -507,6 +507,39 @@ def pole_residue(self):
name=self.name,
)

@classmethod
def from_dispersion(cls, n: float, freq: float, dn_dwvl: float = 0):
"""Convert ``n`` and wavelength dispersion ``dn_dwvl`` values at frequency ``freq`` to
a single-pole :class:`Sellmeier` medium.
Parameters
----------
n : float
Real part of refractive index. Must be larger than or equal to one.
dn_dwvl : float = 0
Derivative of the refractive index with wavelength (1/um). Must be negative.
frequency : float
Frequency to evaluate permittivity at (Hz).
Returns
-------
:class:`Medium`
medium containing the corresponding ``permittivity`` and ``conductivity``.
"""

if dn_dwvl >= 0:
raise ValidationError("Dispersion ``dn_dwvl`` must be smaller than zero.")
if n < 1:
raise ValidationError("Refractive index ``n`` cannot be smaller than one.")

wvl = C_0 / freq
nsqm1 = n ** 2 - 1
c_coeff = -(wvl ** 3) * n * dn_dwvl / (nsqm1 - wvl * n * dn_dwvl)
b_coeff = (wvl ** 2 - c_coeff) / wvl ** 2 * nsqm1
coeffs = [(b_coeff, c_coeff)]

return cls(coeffs=coeffs)


class Lorentz(DispersiveMedium):
"""A dispersive medium described by the Lorentz model.
Expand Down
2 changes: 1 addition & 1 deletion tidy3d/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Tidy3dKeyError(Tidy3dError):


class ValidationError(Tidy3dError):
"""eError when constructing Tidy3d components."""
"""Error when constructing Tidy3d components."""


class SetupError(Tidy3dError):
Expand Down

0 comments on commit 2a13235

Please sign in to comment.