Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add multi-pole Drude medium #73

Merged
merged 1 commit into from
Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ Mediums
Sellmeier
Debye
Lorentz
Drude

Methods
-------
Expand Down
18 changes: 16 additions & 2 deletions tests/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,11 @@ def test_medium_dispersion():
m_PR = PoleResidue(eps_inf=1.0, poles=[(1 + 2j, 1 + 3j), (2 + 4j, 1 + 5j)])
m_SM = Sellmeier(coeffs=[(2, 3), (2, 4)])
m_LZ = Lorentz(eps_inf=1.0, coeffs=[(1, 3, 2), (2, 4, 1)])
m_DR = Drude(eps_inf=1.0, coeffs=[(1, 3), (2, 4)])
m_DB = Debye(eps_inf=1.0, coeffs=[(1, 3), (2, 4)])

freqs = np.linspace(0.01, 1, 1001)
for medium in [m_PR, m_SM, m_LZ, m_DB]:
for medium in [m_PR, m_SM, m_LZ, m_DR, m_DB]:
eps_c = medium.eps_model(freqs)


Expand All @@ -230,15 +231,28 @@ def test_medium_dispersion_conversion():
m_PR = PoleResidue(eps_inf=1.0, poles=[((1 + 2j), (1 + 3j)), ((2 + 4j), (1 + 5j))])
m_SM = Sellmeier(coeffs=[(2, 3), (2, 4)])
m_LZ = Lorentz(eps_inf=1.0, coeffs=[(1, 3, 2), (2, 4, 1)])
m_DR = Drude(eps_inf=1.0, coeffs=[(1, 3), (2, 4)])
m_DB = Debye(eps_inf=1.0, coeffs=[(1, 3), (2, 4)])

freqs = np.linspace(0.01, 1, 1001)
for medium in [m_PR, m_SM, m_DB, m_LZ]: # , m_DB]:
for medium in [m_PR, m_SM, m_DB, m_LZ, m_DR]: # , m_DB]:
eps_model = medium.eps_model(freqs)
eps_pr = medium.pole_residue.eps_model(freqs)
np.testing.assert_allclose(eps_model, eps_pr)


def test_medium_dispersion_create():

m_PR = PoleResidue(eps_inf=1.0, poles=[((1 + 2j), (1 + 3j)), ((2 + 4j), (1 + 5j))])
m_SM = Sellmeier(coeffs=[(2, 3), (2, 4)])
m_LZ = Lorentz(eps_inf=1.0, coeffs=[(1, 3, 2), (2, 4, 1)])
m_DR = Drude(eps_inf=1.0, coeffs=[(1, 3), (2, 4)])
m_DB = Debye(eps_inf=1.0, coeffs=[(1, 3), (2, 4)])

for medium in [m_PR, m_SM, m_DB, m_LZ, m_DR]:
struct = Structure(geometry=Box(size=(1, 1, 1)), medium=medium)


""" modes """


Expand Down
3 changes: 2 additions & 1 deletion tidy3d/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from .components import Box, Sphere, Cylinder, PolySlab

# medium
from .components import Medium, PoleResidue, Sellmeier, Debye, Lorentz, AnisotropicMedium, PEC
from .components import Medium, PoleResidue, AnisotropicMedium, PEC
from .components import Sellmeier, Debye, Drude, Lorentz
from .components import nk_to_eps_complex, nk_to_eps_sigma, eps_complex_to_nk
from .components import nk_to_medium, eps_sigma_to_eps_complex

Expand Down
2 changes: 1 addition & 1 deletion tidy3d/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .geometry import Geometry

# medium
from .medium import Medium, PoleResidue, Sellmeier, Debye, Lorentz, AnisotropicMedium, PEC
from .medium import Medium, PoleResidue, Sellmeier, Debye, Drude, Lorentz, AnisotropicMedium, PEC
from .medium import nk_to_eps_complex, nk_to_eps_sigma, eps_complex_to_nk
from .medium import nk_to_medium, eps_sigma_to_eps_complex

Expand Down
82 changes: 81 additions & 1 deletion tidy3d/components/medium.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,84 @@ def pole_residue(self):
)


class Drude(DispersiveMedium):
"""A dispersive medium described by the Drude model.
The frequency-dependence of the complex-valued permittivity is described by:

.. math::
\\epsilon(f) = \\epsilon_\\infty - \\sum_i
\\frac{ f_i^2}{f^2 - jf\\delta_i}

where :math:`f, f_i, \\delta_i` are in Hz.

Parameters
----------
eps_inf : float = 1.0
Relative permittivity at infinite frequency (:math:`\\epsilon_\\infty`).
coeffs : List[Tuple[float, float]]
List of (:math:`f_i, \\delta_i`) values for model.
frequeuncy_range : Tuple[float, float] = (-inf, inf)
Range of validity for the medium in Hz.
If simulation or plotting functions use frequency out of this range, a warning is thrown.
name : str = None
Optional name for the medium.

Example
-------
>>> drude_medium = Drude(eps_inf=2.0, coeffs=[(1,2), (3,4)])
>>> eps = drude_medium.eps_model(200e12)
"""

eps_inf: float = 1.0
coeffs: List[Tuple[float, float]]
type: Literal["Drude"] = "Drude"

@ensure_freq_in_range
def eps_model(self, frequency: float) -> complex:
"""Complex-valued permittivity as a function of frequency.

Parameters
----------
frequency : float
Frequency to evaluate permittivity at (Hz).

Returns
-------
complex
Complex-valued relative permittivity evaluated at the frequency.
"""
eps = self.eps_inf + 0.0j
for (f, delta) in self.coeffs:
eps -= (f ** 2) / (frequency ** 2 - 1j * frequency * delta)
return eps

@property
def pole_residue(self):
"""Representation of Medium as a pole-residue model."""

poles = []
for (f, delta) in self.coeffs:

w = 2 * np.pi * f
d = 2 * np.pi * delta

c0 = -(w ** 2) / 2 / d + 0j
a0 = 0j

c1 = w ** 2 / 2 / d + 0j
a1 = d + 0j

poles.append((a0, c0))
poles.append((a1, c1))

return PoleResidue(
eps_inf=self.eps_inf,
poles=poles,
frequency_range=self.frequency_range,
name=self.name,
)


class Debye(DispersiveMedium):
"""A dispersive medium described by the Debye model.
The frequency-dependence of the complex-valued permittivity is described by:
Expand Down Expand Up @@ -581,7 +659,9 @@ def pole_residue(self):


# types of mediums that can be used in Simulation and Structures
MediumType = Union[Literal[PEC], Medium, AnisotropicMedium, PoleResidue, Sellmeier, Lorentz, Debye]
MediumType = Union[
Literal[PEC], Medium, AnisotropicMedium, PoleResidue, Sellmeier, Lorentz, Debye, Drude
]

""" Conversion helper functions """

Expand Down