Skip to content

meow

MEOW: Modeling of Eigenmodes and Overlaps in Waveguides.

Modules:

Name Description
arrays

MEOW array tools for pydantic models.

base_model

The pydantic base model all other models are based on.

cell

an EME Cell.

cross_section

A CrossSection.

eme

SAX EME.

environment

One place to gather your environment settings.

fde

FDE Implementations & Backends.

gds_structures

GDS Extrusions.

geometries

MEOW geometries.

materials

Meow Materials.

mesh

A 2D Mesh.

mode

An EigenMode.

structures

A Structure is a combination of a Geometry with a material.

visualization

Visualizations for common meow-datatypes.

Classes:

Name Description
BaseModel

Base model class for all models.

Box

A Box is a simple rectangular cuboid.

Cell

An EME Cell.

CrossSection

A CrossSection is built from a Cell with an Environment.

Environment

An environment contains all variables that don't depend on the structure.

GdsExtrusionRule

A GdsExtrusionRule describes a single extrusion rule.

Geometry2DBase

Base class for 2D geometries.

Geometry3DBase

Base class for 3D geometries.

IndexMaterial

A material with a constant refractive index.

MaterialBase

a Material defines the index of a Structure3D in an Environment.

Mesh2D

A Mesh2D describes how a Structure3D is discritized into a Cell.

Mode

A Mode contains the field information for a given CrossSection.

ModelMetaclass

Metaclass for all models.

Polygon2D

A 2D polygon defined by a list of vertices.

Prism

A prism is a 2D Polygon extruded along a axis direction ('x', 'y', 'z').

Rectangle

A Rectangle.

SampledMaterial

A material with a sampled refractive index.

SerializedArray

A serialized representation of a numpy array.

Structure2D

A Structure2D is an association between a Geometry2D and a Material.

Structure3D

A Structure3D is an association between a Geometry3D and a Material.

TidyMaterial

A material from the Tidy3D material library.

Functions:

Name Description
DType

Validator to ensure the array has a specific dtype.

Dim

Validator to ensure the array has a specific number of dimensions.

Shape

Validator to ensure the array has a specific shape.

Structure

Create a Structure from a Material and Geometry.

cache

Decorator to cache the result of a property method.

cached_property

Decorator to cache the result of a property method.

compute_interface_s_matrices

Compute interface S-matrices for each adjacent pair of mode sets.

compute_interface_s_matrix

Compute the interface S-matrix between two modal bases.

compute_mode_amplitudes

Solve for the forward and backward modal amplitudes in one cell.

compute_modes_lumerical

Compute Modes` for a givenFdeSpec` (Lumerical backend).

compute_modes_tidy3d

Compute Modes for a given CrossSection.

compute_propagation_s_matrices

Return the propagation S-matrix for every cell in a stack.

compute_propagation_s_matrix

Return the diagonal propagation S-matrix for one cell.

compute_s_matrix_sax

Calculate the S-matrix for given sets of modes.

create_cells

Create multiple Cell objects with a Mesh and a collection of cell lengths.

create_lumerical_geometries

Create Lumerical geometries from a list of structures.

downselect_s

Downselect the S-matrix to the given ports.

electric_energy

Get the electric energy contained in a Mode.

electric_energy_density

Get the electric energy density contained in a Mode.

energy

Get the energy contained in a Mode.

energy_density

Get the energy density contained in a Mode.

enforce_passivity

Project singular values onto a passive interval.

extrude_gds

Extrude a gds cell given a dictionary of extruson rules.

filter_modes

Filter a set of modes according to certain criteria.

get_sim

Get the Lumerical simulation object.

inner_product

The modal inner product for z-normal mode planes.

invert_mode

Invert a Mode.

is_lossy_mode

Check whether a mode can be considered lossy.

is_pml_mode

Check whether a mode can be considered a PML mode.

l2r_matrices

Return cumulative left-to-right S-matrices.

magnetic_energy

Get the magnetic energy contained in a Mode.

magnetic_energy_density

Get the magnetic energy density contained in a Mode.

normalize

Normalize a Mode according to the inner_product with itself.

normalize_energy

Normalize a mode according to the energy it contains.

normalize_modes

Self-normalize a set of modes.

orthonormalize_modes

Gram-Schmidt orthonormalization with drop tolerance.

overlap_matrix

Build the modal overlap matrix between two mode sets.

pi_pairs

Return propagation-interface pairs for a full stack.

plot_fields

Reconstruct an Ex(x, z) field slice from propagated modal amplitudes.

pml_fraction

Fraction of energy density in the PML region.

post_process_modes

Default post-processing pipeline after FDE.

propagate

Propagate boundary excitations through cumulative S-matrices.

propagate_modes

Propagate modal excitations through a stack of cells.

r2l_matrices

Return cumulative right-to-left S-matrices.

select_ports

Keep a subset of ports from an S-matrix.

sort_structures

Sort structures by mesh order, then by order of definition.

split_square_matrix

Split a square matrix into its four block submatrices.

te_fraction

The TE polarization fraction of the Mode.

track_modes

Track modal order and phase continuously across a cell stack.

tsvd_solve

Solve A X = B with a truncated-SVD pseudoinverse.

visualize

Visualize any meow object.

zero_phase

Normalize (zero out) the phase of a Mode.

BaseModel

Bases: BaseModel

Base model class for all models.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

Box

Bases: Geometry3DBase

A Box is a simple rectangular cuboid.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

Cell

Bases: BaseModel

An EME Cell.

This defines an interval in z (the direction of propagation) within the simulation domain. The intersecting Structure3Ds are discretized by a given mesh at the center of the Cell

Methods:

Name Description
m_full

The full material mask for the cell.

materials

A mapping of the materials in the cell to their indices.

model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

structures_2d

The 2D structures in the cell.

Attributes:

Name Type Description
length float

The length of the cell.

z float

The z-position of the center of the cell.

length property

length: float

The length of the cell.

z property

z: float

The z-position of the center of the cell.

m_full

m_full() -> IntArray2D

The full material mask for the cell.

Source code in src/meow/cell.py
@cached_property
def m_full(self) -> IntArray2D:
    """The full material mask for the cell."""
    return _create_full_material_array(
        mesh=self.mesh,
        structures=self.structures_2d,
        materials=self.materials,
    )

materials

materials() -> dict[Material, int]

A mapping of the materials in the cell to their indices.

Source code in src/meow/cell.py
@cached_property
def materials(self) -> dict[Material, int]:
    """A mapping of the materials in the cell to their indices."""
    materials = {}
    for i, structure in enumerate(sort_structures(self.structures), start=1):
        if structure.material not in materials:
            materials[structure.material] = i
    return materials

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

structures_2d

structures_2d() -> list[Structure2D]

The 2D structures in the cell.

Source code in src/meow/cell.py
@cached_property
def structures_2d(self) -> list[Structure2D]:
    """The 2D structures in the cell."""
    z = 0.5 * (self.z_min + self.z_max)
    list_of_list = [s._project(z) for s in self.structures]
    structures = [s for ss in list_of_list for s in ss]
    return structures

CrossSection

Bases: BaseModel

A CrossSection is built from a Cell with an Environment.

This uniquely defines the refractive index everywhere.

Methods:

Name Description
from_cell

Create a CrossSection from a Cell and Environment.

materials

Return a dictionary mapping materials to their indices.

model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

n_full

Return the refractive index array for the full mesh.

nx

Return the smoothed refractive index on the Ex positions.

ny

Return the smoothed refractive index on the Ey positions.

nz

Return the smoothed refractive index on the Ez positions.

from_cell classmethod

from_cell(
    *,
    cell: Cell,
    env: Environment,
    subpixel_smoothing: bool = True,
) -> Self

Create a CrossSection from a Cell and Environment.

Source code in src/meow/cross_section.py
@classmethod
def from_cell(
    cls,
    *,
    cell: Cell,
    env: Environment,
    subpixel_smoothing: bool = True,
) -> Self:
    """Create a CrossSection from a Cell and Environment."""
    return cls(
        structures=cell.structures_2d,
        mesh=cell.mesh,
        env=env,
        subpixel_smoothing=subpixel_smoothing,
        _cell=cell,
    )

materials

materials() -> dict[Material, int]

Return a dictionary mapping materials to their indices.

Source code in src/meow/cross_section.py
@cached_property
def materials(self) -> dict[Material, int]:
    """Return a dictionary mapping materials to their indices."""
    materials: dict[Material, int] = {}
    for i, structure in enumerate(sort_structures(self.structures), start=1):
        if structure.material not in materials:
            materials[structure.material] = i
    return materials

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

n_full

n_full() -> ComplexArray2D

Return the refractive index array for the full mesh.

Source code in src/meow/cross_section.py
@cached_property
def n_full(self) -> ComplexArray2D:
    """Return the refractive index array for the full mesh."""
    n_full = np.ones_like(self.mesh.X_full, dtype=np.complex128)
    for material, idx in self.materials.items():
        n_full = np.where(self._m_full == idx, material(self.env), n_full)
    return n_full

nx

nx() -> ComplexArray2D

Return the smoothed refractive index on the Ex positions.

Source code in src/meow/cross_section.py
@cached_property
def nx(self) -> ComplexArray2D:
    """Return the smoothed refractive index on the Ex positions."""
    if self.subpixel_smoothing:
        return _compute_smoothed_n(
            self.mesh, self._m_full, self.materials, self.env, self.structures, "x"
        )
    return _compute_winner_takes_all_n(
        self.mesh, self._m_full, self.materials, self.env, self.structures, "x"
    )

ny

ny() -> ComplexArray2D

Return the smoothed refractive index on the Ey positions.

Source code in src/meow/cross_section.py
@cached_property
def ny(self) -> ComplexArray2D:
    """Return the smoothed refractive index on the Ey positions."""
    if self.subpixel_smoothing:
        return _compute_smoothed_n(
            self.mesh, self._m_full, self.materials, self.env, self.structures, "y"
        )
    return _compute_winner_takes_all_n(
        self.mesh, self._m_full, self.materials, self.env, self.structures, "y"
    )

nz

nz() -> ComplexArray2D

Return the smoothed refractive index on the Ez positions.

Source code in src/meow/cross_section.py
@cached_property
def nz(self) -> ComplexArray2D:
    """Return the smoothed refractive index on the Ez positions."""
    if self.subpixel_smoothing:
        return _compute_smoothed_n(
            self.mesh, self._m_full, self.materials, self.env, self.structures, "z"
        )
    return _compute_winner_takes_all_n(
        self.mesh, self._m_full, self.materials, self.env, self.structures, "z"
    )

Environment

Bases: BaseModel

An environment contains all variables that don't depend on the structure.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

GdsExtrusionRule

Bases: BaseModel

A GdsExtrusionRule describes a single extrusion rule.

Multiple of such rules can later be associated with a gds layer tuple.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

Geometry2DBase

Bases: BaseModel

Base class for 2D geometries.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

Geometry3DBase

Bases: BaseModel

Base class for 3D geometries.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

IndexMaterial

Bases: MaterialBase

A material with a constant refractive index.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

MaterialBase

Bases: BaseModel

a Material defines the index of a Structure3D in an Environment.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

Mesh2D

Bases: BaseModel

A Mesh2D describes how a Structure3D is discritized into a Cell.

Methods:

Name Description
XY_full

X and Y at half-integer locations.

dx

dx at Hz locations, i.e. center of the 2D cell.

dy

dy at Hz locations, i.e. center of the 2D cell.

model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

x_

x at Hz locations, i.e. center of the 2D cell.

x_full

x at half-integer locations.

y_

y at Hz locations, i.e. center of the 2D cell.

y_full

y at half-integer locations.

Attributes:

Name Type Description
X_full FloatArray2D

X at half-integer locations.

Xx FloatArray2D

X at Ex locations.

Xy FloatArray2D

X at Ey locations.

Xz FloatArray2D

X at Ez locations.

Xz_ FloatArray2D

X at Hz locations.

Y_full FloatArray2D

Y at half-integer locations.

Yx FloatArray2D

Y at Ex locations.

Yy FloatArray2D

Y at Ey locations.

Yz FloatArray2D

Y at Ez locations.

Yz_ FloatArray2D

Y at Hz locations.

X_full property

X_full: FloatArray2D

X at half-integer locations.

Xx property

Xx: FloatArray2D

X at Ex locations.

Xy property

Xy: FloatArray2D

X at Ey locations.

Xz property

Xz: FloatArray2D

X at Ez locations.

Xz_ property

Xz_: FloatArray2D

X at Hz locations.

Y_full property

Y_full: FloatArray2D

Y at half-integer locations.

Yx property

Yx: FloatArray2D

Y at Ex locations.

Yy property

Yy: FloatArray2D

Y at Ey locations.

Yz property

Yz: FloatArray2D

Y at Ez locations.

Yz_ property

Yz_: FloatArray2D

Y at Hz locations.

XY_full

XY_full() -> tuple[FloatArray2D, FloatArray2D]

X and Y at half-integer locations.

Source code in src/meow/mesh.py
@cached_property
def XY_full(self) -> tuple[FloatArray2D, FloatArray2D]:
    """X and Y at half-integer locations."""
    Y_full, X_full = np.meshgrid(self.y_full, self.x_full)
    return X_full, Y_full

dx

dx() -> FloatArray1D

dx at Hz locations, i.e. center of the 2D cell.

Source code in src/meow/mesh.py
@cached_property
def dx(self) -> FloatArray1D:
    """dx at Hz locations, i.e. center of the 2D cell."""
    return self.x[1:] - self.x[:-1]

dy

dy() -> FloatArray1D

dy at Hz locations, i.e. center of the 2D cell.

Source code in src/meow/mesh.py
@cached_property
def dy(self) -> FloatArray1D:
    """dy at Hz locations, i.e. center of the 2D cell."""
    return self.y[1:] - self.y[:-1]

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

x_

x_() -> FloatArray1D

x at Hz locations, i.e. center of the 2D cell.

Source code in src/meow/mesh.py
@cached_property
def x_(self) -> FloatArray1D:
    """x at Hz locations, i.e. center of the 2D cell."""
    return 0.5 * (self.x[1:] + self.x[:-1])

x_full

x_full() -> FloatArray1D

x at half-integer locations.

Source code in src/meow/mesh.py
@cached_property
def x_full(self) -> FloatArray1D:
    """x at half-integer locations."""
    return np.stack([self.x[:-1], self.x[:-1] + self.dx / 2], 1).ravel()

y_

y_() -> FloatArray1D

y at Hz locations, i.e. center of the 2D cell.

Source code in src/meow/mesh.py
@cached_property
def y_(self) -> FloatArray1D:
    """y at Hz locations, i.e. center of the 2D cell."""
    return 0.5 * (self.y[1:] + self.y[:-1])

y_full

y_full() -> FloatArray1D

y at half-integer locations.

Source code in src/meow/mesh.py
@cached_property
def y_full(self) -> FloatArray1D:
    """y at half-integer locations."""
    return np.stack([self.y[:-1], self.y[:-1] + self.dy / 2], 1).ravel()

Mode

Bases: BaseModel

A Mode contains the field information for a given CrossSection.

Methods:

Name Description
interpolate

Interpolate the mode to the given location.

load

Load a mode from a file.

model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

save

Save the mode to a file.

Attributes:

Name Type Description
Px ComplexArray2D

The x-component of the Poynting vector.

Py ComplexArray2D

The y-component of the Poynting vector.

Pz ComplexArray2D

The z-component of the Poynting vector.

env Environment

The environment of the mode.

mesh Mesh2D

The mesh of the mode.

te_fraction float

The TE polarization fraction of the mode.

Px property

Px: ComplexArray2D

The x-component of the Poynting vector.

Py property

Py: ComplexArray2D

The y-component of the Poynting vector.

Pz property

Pz: ComplexArray2D

The z-component of the Poynting vector.

env property

The environment of the mode.

mesh property

mesh: Mesh2D

The mesh of the mode.

te_fraction property

te_fraction: float

The TE polarization fraction of the mode.

interpolate

interpolate(
    location: Literal["Ex", "Ey", "Ez", "Hx", "Hy", "Hz"]
    | None,
) -> Mode

Interpolate the mode to the given location.

Source code in src/meow/mode.py
def interpolate(
    self,
    location: Literal["Ex", "Ey", "Ez", "Hx", "Hy", "Hz"] | None,
) -> Mode:
    """Interpolate the mode to the given location."""
    if location is None or location == self.interpolation:
        return self
    if self.interpolation != "":
        msg = "Cannot interpolate from already interpolated mode!"
        raise RuntimeError(msg)
    interpolate_funcs = {
        "EX": _interpolate_Ex,
        "EY": _interpolate_Ey,
        "EZ": _interpolate_Ez,
        "HX": _interpolate_Ey,
        "HY": _interpolate_Ex,
        "HZ": _interpolate_Hz,
    }
    interpolate_func = interpolate_funcs[location.upper()]
    return interpolate_func(self)

load classmethod

load(filename: str | Path) -> Mode

Load a mode from a file.

Source code in src/meow/mode.py
@classmethod
def load(cls, filename: str | Path) -> Mode:
    """Load a mode from a file."""
    return cast(Mode, pickle.loads(Path(filename).read_bytes()))

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

save

save(filename: str | Path) -> None

Save the mode to a file.

Source code in src/meow/mode.py
def save(self, filename: str | Path) -> None:
    """Save the mode to a file."""
    path = Path(filename)
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_bytes(pickle.dumps(self))

ModelMetaclass

Bases: ModelMetaclass

Metaclass for all models.

Polygon2D

Bases: Geometry2DBase

A 2D polygon defined by a list of vertices.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

Prism

Bases: Geometry3DBase

A prism is a 2D Polygon extruded along a axis direction ('x', 'y', 'z').

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

Rectangle

Bases: Geometry2DBase

A Rectangle.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

SampledMaterial

Bases: MaterialBase

A material with a sampled refractive index.

Methods:

Name Description
from_df

Create a SampledMaterial from a DataFrame.

from_path

Create a SampledMaterial from a CSV file.

model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

from_df classmethod

from_df(
    name: str, df: DataFrame, meta: dict | None = None
) -> Self

Create a SampledMaterial from a DataFrame.

Source code in src/meow/materials.py
@classmethod
def from_df(cls, name: str, df: pd.DataFrame, meta: dict | None = None) -> Self:
    """Create a SampledMaterial from a DataFrame."""
    meta = meta or {}

    nr = df["nr"].to_numpy()
    ni = np.zeros_like(nr) if "ni" not in df else df["ni"].to_numpy()
    n = nr + 1j * ni

    columns = [c for c in df.columns if c not in ["nr", "ni"]]
    params = {c: np.asarray(df[c].values, dtype=np.float64) for c in columns}

    return cls(name=name, params=params, n=n, meta=meta)

from_path classmethod

from_path(path: str, meta: dict | None = None) -> Self

Create a SampledMaterial from a CSV file.

Source code in src/meow/materials.py
@classmethod
def from_path(cls, path: str, meta: dict | None = None) -> Self:
    """Create a SampledMaterial from a CSV file."""
    path = _validate_path(path)
    name = re.sub(r"\.csv$", "", os.path.split(path)[-1])
    df = pd.read_csv(path)
    return cls.from_df(name, df, meta=meta)

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

SerializedArray

Bases: BaseModel

A serialized representation of a numpy array.

Methods:

Name Description
from_array

Create a SerializedArray from a numpy array.

to_array

Convert the SerializedArray back to a numpy array.

from_array classmethod

from_array(x: ndarray) -> Self

Create a SerializedArray from a numpy array.

Source code in src/meow/arrays.py
@classmethod
def from_array(cls, x: np.ndarray) -> Self:
    """Create a SerializedArray from a numpy array."""
    x = np.asarray(x)
    shape = x.shape
    dtype = str(x.dtype)
    if dtype == "complex64":
        _x = x.ravel().view("float32")
    elif dtype == "complex128":
        _x = x.ravel().view("float64")
    else:
        _x = x.ravel()
    return cls(shape=shape, dtype=dtype, values=_x.tolist())

to_array

to_array() -> ndarray

Convert the SerializedArray back to a numpy array.

Source code in src/meow/arrays.py
def to_array(self) -> np.ndarray:
    """Convert the SerializedArray back to a numpy array."""
    if self.dtype == "complex128":
        arr = np.asarray(self.values, dtype="float64").view("complex128")
    elif self.dtype == "complex64":
        arr = np.asarray(self.values, dtype="float32").view("complex64")
    else:
        arr = np.asarray(self.values, dtype=self.dtype)

    if not self.shape:
        return arr
    return arr.reshape(*self.shape)

Structure2D

Bases: BaseModel

A Structure2D is an association between a Geometry2D and a Material.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

Structure3D

Bases: BaseModel

A Structure3D is an association between a Geometry3D and a Material.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

TidyMaterial

TidyMaterial(**kwargs: Any)

Bases: MaterialBase

A material from the Tidy3D material library.

Methods:

Name Description
model_validate

Validate a pydantic model instance.

model_validate_json

Validate a pydantic model instance.

Source code in src/meow/materials.py
def __init__(self, **kwargs: Any) -> None:
    """Initialize the TidyMaterial."""
    super().__init__(**kwargs)

    if self.name not in material_library:
        msg = (
            "Specified material name is invalid. "
            f"Use one of {material_library.keys()}"
        )
        raise ValueError(msg)
    _material = material_library[self.name]
    _variants = getattr(_material, "variants", {})
    if not _variants:
        msg = f"Tidy3D material '{self.name}' not supported."
        raise ValueError(msg)
    if self.variant not in _variants:
        _variant_options = list(_variants.keys())
        msg = f"Specified variant is invalid. Use one of {_variant_options}."
        raise ValueError(msg)

model_validate classmethod

model_validate(
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
obj Any

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes bool | None

Whether to extract data from object attributes.

None
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    obj: Any,
    *,
    strict: bool | None = None,
    from_attributes: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        obj: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    __tracebackhide__ = True

    if isinstance(obj, cls):
        return obj

    if isinstance(obj, dict):
        cls = MODELS.get(obj.get("type", cls.__name__), cls)  # noqa: PLW0642

    return cls.__pydantic_validator__.validate_python(
        obj, strict=strict, from_attributes=from_attributes, context=context
    )

model_validate_json classmethod

model_validate_json(
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self

Validate a pydantic model instance.

Parameters:

Name Type Description Default
json_data str | bytes | bytearray

The object to validate.

required
strict bool | None

Whether to enforce types strictly.

None
from_attributes

Whether to extract data from object attributes.

required
context dict[str, Any] | None

Additional context to pass to the validator.

None

Raises:

Type Description
ValidationError

If the object could not be validated.

Returns:

Type Description
Self

The validated model instance.

Source code in src/meow/base_model.py
@classmethod
def model_validate_json(  # type: ignore[reportIncompatibleMethodOverride]
    cls,
    json_data: str | bytes | bytearray,
    *,
    strict: bool | None = None,
    context: dict[str, Any] | None = None,
) -> Self:
    """Validate a pydantic model instance.

    Args:
        json_data: The object to validate.
        strict: Whether to enforce types strictly.
        from_attributes: Whether to extract data from object attributes.
        context: Additional context to pass to the validator.

    Raises:
        ValidationError: If the object could not be validated.

    Returns:
        The validated model instance.
    """
    if isinstance(json_data, str):
        json_data = json_data.encode()
    dct = orjson.loads(json_data)
    return cls.model_validate(dct, strict=strict, context=context)

DType

DType(dtype: str, *, coerce: bool = True) -> AfterValidator

Validator to ensure the array has a specific dtype.

Source code in src/meow/arrays.py
def DType(dtype: str, *, coerce: bool = True) -> AfterValidator:  # noqa: N802
    """Validator to ensure the array has a specific dtype."""
    f = _coerce_dtype if coerce else _assert_dtype
    return AfterValidator(partial(f, dtype=dtype))

Dim

Dim(ndim: int, *, coerce: bool = True) -> AfterValidator

Validator to ensure the array has a specific number of dimensions.

Source code in src/meow/arrays.py
def Dim(ndim: int, *, coerce: bool = True) -> AfterValidator:  # noqa: N802
    """Validator to ensure the array has a specific number of dimensions."""
    f = _coerce_dim if coerce else _assert_dim
    return AfterValidator(partial(f, ndim=ndim))

Shape

Shape(*shape: int, coerce: bool = True) -> AfterValidator

Validator to ensure the array has a specific shape.

Source code in src/meow/arrays.py
def Shape(*shape: int, coerce: bool = True) -> AfterValidator:  # noqa: N802
    """Validator to ensure the array has a specific shape."""
    f = _coerce_shape if coerce else _assert_shape
    return AfterValidator(partial(f, shape=shape))

Structure

Structure(
    *,
    material: Material,
    geometry: Geometry2D,
    mesh_order: int = DEFAULT_MESH_ORDER,
) -> Structure2D
Structure(
    *,
    material: Material,
    geometry: Geometry3D,
    mesh_order: int = DEFAULT_MESH_ORDER,
) -> Structure3D
Structure(
    *,
    material: Material,
    geometry: Geometry2D | Geometry3D,
    mesh_order: int = DEFAULT_MESH_ORDER,
) -> Structure2D | Structure3D

Create a Structure from a Material and Geometry.

Source code in src/meow/structures.py
def Structure(  # noqa: N802
    *,
    material: Material,
    geometry: Geometry2D | Geometry3D,
    mesh_order: int = DEFAULT_MESH_ORDER,
) -> Structure2D | Structure3D:
    """Create a Structure from a Material and Geometry."""
    kwargs = {
        "material": material,
        "geometry": geometry,
        "mesh_order": mesh_order,
    }
    if isinstance(geometry, Geometry2D):
        return Structure2D(**kwargs)
    return Structure3D(**kwargs)

cache

cache(prop: Callable) -> Callable

Decorator to cache the result of a property method.

Source code in src/meow/base_model.py
def cache(prop: Callable) -> Callable:
    """Decorator to cache the result of a property method."""
    prop_name = getattr(prop, "__name__", "")
    if not prop_name:
        return prop

    @wraps(prop)
    def getter(self):  # noqa: ANN001,ANN202
        stored_value = self._cache.get(prop_name)

        if stored_value is not None:
            return stored_value

        computed = prop(self)
        self._cache[prop_name] = computed
        return computed

    return getter

cached_property

cached_property(method: Callable)

Decorator to cache the result of a property method.

Source code in src/meow/base_model.py
def cached_property(method: Callable):  # noqa: ANN201
    """Decorator to cache the result of a property method."""
    return property(cache(method))

compute_interface_s_matrices

compute_interface_s_matrices(
    modes: list[Modes],
    *,
    inner_product: Callable = inner_product,
    conjugate: bool | None = None,
    tsvd_rcond: float = 0.001,
    passivity_method: PassivityMethod = "invert",
    enforce_reciprocity: bool = True,
    ignore_warnings: bool = True,
) -> dict[str, SDenseMM]

Compute interface S-matrices for each adjacent pair of mode sets.

This is a thin wrapper around :func:compute_interface_s_matrix applied to every neighboring pair in modes.

The same sharp edges apply here as for the single-interface solve: orthonormalization, inner-product choice, TSVD cutoff, and passivity method must all be interpreted consistently across the full stack.

Source code in src/meow/eme/interface.py
def compute_interface_s_matrices(
    modes: list[Modes],
    *,
    inner_product: Callable = inner_product,
    conjugate: bool | None = None,
    tsvd_rcond: float = 1e-3,
    passivity_method: PassivityMethod = "invert",
    enforce_reciprocity: bool = True,
    ignore_warnings: bool = True,
) -> dict[str, sax.SDenseMM]:
    """Compute interface S-matrices for each adjacent pair of mode sets.

    This is a thin wrapper around :func:`compute_interface_s_matrix` applied to
    every neighboring pair in ``modes``.

    The same sharp edges apply here as for the single-interface solve:
    orthonormalization, inner-product choice, TSVD cutoff, and passivity method
    must all be interpreted consistently across the full stack.
    """
    return {
        f"i_{i}_{i + 1}": compute_interface_s_matrix(
            modes1=modes1,
            modes2=modes2,
            inner_product=inner_product,
            conjugate=conjugate,
            tsvd_rcond=tsvd_rcond,
            passivity_method=passivity_method,
            enforce_reciprocity=enforce_reciprocity,
            ignore_warnings=ignore_warnings,
        )
        for i, (modes1, modes2) in enumerate(pairwise(modes))
    }

compute_interface_s_matrix

compute_interface_s_matrix(
    modes1: Modes,
    modes2: Modes,
    *,
    inner_product: Callable = inner_product,
    conjugate: bool | None = None,
    tsvd_rcond: float = 0.001,
    passivity_method: PassivityMethod = "invert",
    enforce_reciprocity: bool = True,
    ignore_warnings: bool = True,
) -> SDenseMM

Compute the interface S-matrix between two modal bases.

This implements the overlap-based EME interface solve for a step discontinuity. The transmission blocks are obtained from a TSVD-regularized solve, then the reflection blocks are reconstructed from the two continuity equations and averaged:

  • R_LL = 0.5 * ((O_RL^adj @ T_LR - I) + (I - O_LR @ T_LR))
  • R_RR = 0.5 * ((O_LR^adj @ T_RL - I) + (I - O_RL @ T_RL))
High-level assumptions
  • the supplied mode sets are already orthonormalized in the same metric used by inner_product;
  • the interface formulas are therefore used in their simplified G = I form;
  • any remaining non-passivity is treated as a numerical/truncation issue and corrected afterwards via singular-value processing.
Sharp edges
  • If modes were orthonormalized with a different inner product than the one passed here, the result is not physically meaningful.
  • conjugate must match the intended overlap convention. If omitted, it is inferred from inner_product.
  • tsvd_rcond controls a stability/accuracy tradeoff. Too small can amplify ill-conditioned directions; too large can discard physically relevant channels.
  • passivity correction modifies the raw interface solve. This is often necessary for truncated bases, but it is still a model correction, not a proof that the original solve was complete.

Parameters:

Name Type Description Default
modes1 Modes

Modes on the left side of the interface.

required
modes2 Modes

Modes on the right side of the interface.

required
inner_product Callable

Inner-product callable used to form the overlap matrices. This must be consistent with how the modes were orthonormalized.

inner_product
conjugate bool | None

Whether to use the conjugated (power-conserving) formulation. If None, inferred from the inner_product callable. Must match the conjugate setting used in inner_product for physical consistency: - conjugate=True: uses O_RL.conj().T (Hermitian transpose) - conjugate=False: uses O_RL.T (transpose)

None
tsvd_rcond float

Relative singular-value cutoff for the TSVD solve used to build the transmission blocks.

0.001
passivity_method PassivityMethod

Method for enforcing passivity ("none", "clip", "invert", "subtract").

'invert'
enforce_reciprocity bool

Whether to symmetrize the final S-matrix as 0.5 * (S + S.T).

True
ignore_warnings bool

Whether to suppress numerical warnings.

True

Returns:

Type Description
SDenseMM

A tuple (S, port_map) in SAX dense-matrix format.

Notes

The default path is internally consistent because the default meow.mode.inner_product is the asymmetric, unconjugated overlap and the default mode post-processing uses that same callable. If you change the interface inner product, you should generally use the same callable during mode post-processing.

Source code in src/meow/eme/interface.py
def compute_interface_s_matrix(
    modes1: Modes,
    modes2: Modes,
    *,
    inner_product: Callable = inner_product,
    conjugate: bool | None = None,
    tsvd_rcond: float = 1e-3,
    passivity_method: PassivityMethod = "invert",
    enforce_reciprocity: bool = True,
    ignore_warnings: bool = True,
) -> sax.SDenseMM:
    """Compute the interface S-matrix between two modal bases.

    This implements the overlap-based EME interface solve for a step
    discontinuity. The transmission blocks are obtained from a TSVD-regularized
    solve, then the reflection blocks are reconstructed from the two continuity
    equations and averaged:

    - ``R_LL = 0.5 * ((O_RL^adj @ T_LR - I) + (I - O_LR @ T_LR))``
    - ``R_RR = 0.5 * ((O_LR^adj @ T_RL - I) + (I - O_RL @ T_RL))``

    High-level assumptions:
        - the supplied mode sets are already orthonormalized in the same metric
          used by ``inner_product``;
        - the interface formulas are therefore used in their simplified
          ``G = I`` form;
        - any remaining non-passivity is treated as a numerical/truncation
          issue and corrected afterwards via singular-value processing.

    Sharp edges:
        - If modes were orthonormalized with a different inner product than the
          one passed here, the result is not physically meaningful.
        - ``conjugate`` must match the intended overlap convention. If omitted,
          it is inferred from ``inner_product``.
        - ``tsvd_rcond`` controls a stability/accuracy tradeoff. Too small can
          amplify ill-conditioned directions; too large can discard physically
          relevant channels.
        - passivity correction modifies the raw interface solve. This is often
          necessary for truncated bases, but it is still a model correction, not
          a proof that the original solve was complete.

    Args:
        modes1: Modes on the left side of the interface.
        modes2: Modes on the right side of the interface.
        inner_product: Inner-product callable used to form the overlap matrices.
            This must be consistent with how the modes were orthonormalized.
        conjugate: Whether to use the conjugated (power-conserving) formulation.
            If None, inferred from the inner_product callable. Must match the
            conjugate setting used in inner_product for physical consistency:
            - conjugate=True: uses O_RL.conj().T (Hermitian transpose)
            - conjugate=False: uses O_RL.T (transpose)
        tsvd_rcond: Relative singular-value cutoff for the TSVD solve used to
            build the transmission blocks.
        passivity_method: Method for enforcing passivity
            ("none", "clip", "invert", "subtract").
        enforce_reciprocity: Whether to symmetrize the final S-matrix as
            ``0.5 * (S + S.T)``.
        ignore_warnings: Whether to suppress numerical warnings.

    Returns:
        A tuple ``(S, port_map)`` in SAX dense-matrix format.

    Notes:
        The default path is internally consistent because the default
        ``meow.mode.inner_product`` is the asymmetric, unconjugated overlap and
        the default mode post-processing uses that same callable. If you change
        the interface inner product, you should generally use the same callable
        during mode post-processing.
    """
    if ignore_warnings:
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", message=".*divide by zero.*")
            warnings.filterwarnings("ignore", message=".*overflow encountered.*")
            warnings.filterwarnings("ignore", message=".*invalid value.*")
            return compute_interface_s_matrix(
                modes1=modes1,
                modes2=modes2,
                inner_product=inner_product,
                conjugate=conjugate,
                tsvd_rcond=tsvd_rcond,
                passivity_method=passivity_method,
                enforce_reciprocity=enforce_reciprocity,
                ignore_warnings=False,
            )

    # Infer conjugate from inner_product if not explicitly provided
    if conjugate is None:
        conjugate = _infer_conjugate(inner_product)

    # Supports unequal number of modes on left and right
    N_L, N_R = len(modes1), len(modes2)

    # Overlap matrices: O_LR is (N_L, N_R), O_RL is (N_R, N_L)
    O_LR = overlap_matrix(modes1, modes2, inner_product)
    O_RL = overlap_matrix(modes2, modes1, inner_product)

    I_L = np.eye(N_L)
    I_R = np.eye(N_R)

    # Use Hermitian transpose (.conj().T) for conjugated inner product,
    # plain transpose (.T) for unconjugated inner product.
    # This matches the Lorentz reciprocity relation for each formulation.
    O_RL_adj = O_RL.conj().T if conjugate else O_RL.T
    O_LR_adj = O_LR.conj().T if conjugate else O_LR.T

    # T_LR: (N_R, N_L) — maps N_L left inputs to N_R right outputs
    # Solve: A_LR @ T_LR = 2 * I_L, where A_LR is (N_L, N_R)
    # tsvd_solve(A, B) returns pinv(A) @ B
    # pinv(A_LR) is (N_R, N_L), so result is (N_R, N_L) @ (N_L, N_L) = (N_R, N_L)
    A_LR = O_LR + O_RL_adj  # (N_L, N_R)
    T_LR, *_ = tsvd_solve(A_LR, 2.0 * I_L, rcond=tsvd_rcond)  # (N_R, N_L)

    # T_RL: (N_L, N_R) — maps N_R right inputs to N_L left outputs
    # pinv(A_RL) is (N_L, N_R), so result is (N_L, N_R) @ (N_R, N_R) = (N_L, N_R)
    A_RL = O_RL + O_LR_adj  # (N_R, N_L)
    T_RL, *_ = tsvd_solve(A_RL, 2.0 * I_R, rcond=tsvd_rcond)  # (N_L, N_R)

    # Compute R from both continuity equations and average; this reduces sensitivity
    # to cancellation relative to directly forming (O_RL^adj - O_LR).
    # R_LL: (N_L, N_L)
    R_LL_e = O_RL_adj @ T_LR - I_L  # (N_L, N_R) @ (N_R, N_L) = (N_L, N_L)
    R_LL_h = I_L - O_LR @ T_LR  # (N_L, N_R) @ (N_R, N_L) = (N_L, N_L)
    R_LL = 0.5 * (R_LL_e + R_LL_h)

    # R_RR: (N_R, N_R)
    R_RR_e = O_LR_adj @ T_RL - I_R  # (N_R, N_L) @ (N_L, N_R) = (N_R, N_R)
    R_RR_h = I_R - O_RL @ T_RL  # (N_R, N_L) @ (N_L, N_R) = (N_R, N_R)
    R_RR = 0.5 * (R_RR_e + R_RR_h)

    # Full S-matrix: [a-; b+] = S [a+; b-]
    # Shape: (N_L + N_R, N_L + N_R)
    # Block structure:
    #   [[R_LL (N_L, N_L),  T_RL (N_L, N_R)],
    #    [T_LR (N_R, N_L),  R_RR (N_R, N_R)]]
    S = np.block(
        [
            [R_LL, T_RL],
            [T_LR, R_RR],
        ]
    )

    # Passivity enforcement via SVD
    U, sigma, Vh = np.linalg.svd(S, full_matrices=False)
    sigma_corrected = enforce_passivity(sigma, method=passivity_method)
    S = (U * sigma_corrected) @ Vh

    if enforce_reciprocity:
        S = 0.5 * (S + S.T)

    in_ports = [f"left@{i}" for i in range(N_L)]
    out_ports = [f"right@{i}" for i in range(N_R)]
    port_map = {p: i for i, p in enumerate(in_ports + out_ports)}
    return jnp.asarray(S), port_map

compute_mode_amplitudes

compute_mode_amplitudes(
    u: ComplexArray2D,
    v: ComplexArray2D,
    m: int,
    excitation_l: ComplexArray1D,
    excitation_r: ComplexArray1D,
) -> tuple[ComplexArray1D, ComplexArray1D]

Solve for the forward and backward modal amplitudes in one cell.

Source code in src/meow/eme/propagation.py
def compute_mode_amplitudes(
    u: ComplexArray2D,
    v: ComplexArray2D,
    m: int,
    excitation_l: ComplexArray1D,
    excitation_r: ComplexArray1D,
) -> tuple[ComplexArray1D, ComplexArray1D]:
    """Solve for the forward and backward modal amplitudes in one cell."""
    n = u.shape[0] - m
    _, [u21, u22] = split_square_matrix(u, n)
    [v11, v12], _ = split_square_matrix(v, m)

    rhs = u21 @ excitation_l + u22 @ v12 @ excitation_r
    lhs = np.eye(m, dtype=complex) - u22 @ v11
    forward = np.linalg.solve(lhs, rhs)
    backward = v12 @ excitation_r + v11 @ forward
    return forward, backward

compute_modes_lumerical

compute_modes_lumerical(
    cs: CrossSection,
    num_modes: PositiveInt = 10,
    unit: float = 1e-06,
    post_process: Callable = post_process_modes,
    sim: Sim | None = None,
) -> list[Mode]

Compute Modes` for a givenFdeSpec` (Lumerical backend).

Source code in src/meow/fde/lumerical.py
def compute_modes_lumerical(
    cs: CrossSection,
    num_modes: PositiveInt = 10,
    unit: float = 1e-6,
    post_process: Callable = post_process_modes,
    sim: Sim | None = None,
) -> list[Mode]:
    """Compute ``Modes` for a given ``FdeSpec` (Lumerical backend)."""
    from lumapi import LumApiError  # type: ignore[reportMissingImports]

    sim = get_sim(sim=sim)

    if sim is None:
        msg = "Lumerical simulation object not given or found."
        raise RuntimeError(msg)

    cell = cs._cell

    if cell is None:
        msg = (
            "The cross-section does not have a cell defined. "
            "Please define a cell before computing modes."
        )
        raise ValueError(msg)

    _assert_default_mesh_setting(cell.mesh.angle_phi == 0, "angle_phi")
    _assert_default_mesh_setting(cell.mesh.angle_theta == 0, "angle_theta")
    _assert_default_mesh_setting(cell.mesh.bend_radius is None, "bend_radius")

    create_lumerical_geometries(sim, cell.structures, cs.env, unit)

    sim.select("FDE")
    sim.delete()
    pml_settings = {}
    num_pml_y, num_pml_z = 0, 0
    if cell.mesh.num_pml[0] > 0:
        pml_settings.update(
            {
                "y_min_bc": "PML",
                "y_max_bc": "PML",
            }
        )
        num_pml_y = 22  # TODO: allow adjusting these values
    if cell.mesh.num_pml[1] > 0:
        pml_settings.update(
            {
                "z_min_bc": "PML",
                "z_max_bc": "PML",
            }
        )
        num_pml_z = 22  # TODO: allow adjusting these values
    sim.addfde(
        background_index=1.0,
        solver_type="2D X normal",
        x=float(cell.z * unit),
        y_min=float(cell.mesh.x.min() * unit),
        y_max=float(cell.mesh.x.max() * unit),
        z_min=float(cell.mesh.y.min() * unit),
        z_max=float(cell.mesh.y.max() * unit),
        define_y_mesh_by="number of mesh cells",
        define_z_mesh_by="number of mesh cells",
        mesh_cells_y=cell.mesh.x_.shape[0],
        mesh_cells_z=cell.mesh.y_.shape[0],
        **pml_settings,
    )
    # set mesh size again, because PML messes with it:
    if cell.mesh.num_pml[0] > 0:
        sim.setnamed("FDE", "mesh cells y", cell.mesh.x_.shape[0] - num_pml_y)
    if cell.mesh.num_pml[1] > 0:
        sim.setnamed("FDE", "mesh cells z", cell.mesh.y_.shape[0] - num_pml_z)
    sim.setanalysis("number of trial modes", int(num_modes))
    sim.setanalysis("search", "near n")
    sim.setanalysis("use max index", True)  # noqa: FBT003
    sim.setanalysis("wavelength", float(cs.env.wl * unit))
    sim.findmodes()
    modes = []
    for j in range(1, num_modes + 1):
        try:
            mode = _lumerical_fields_to_mode(
                cs=cs,
                lneff=sim.getdata(f"mode{j}", "neff"),
                lEx=sim.getdata(f"mode{j}", "Ex"),
                lEy=sim.getdata(f"mode{j}", "Ey"),
                lEz=sim.getdata(f"mode{j}", "Ez"),
                lHx=sim.getdata(f"mode{j}", "Hx"),
                lHy=sim.getdata(f"mode{j}", "Hy"),
                lHz=sim.getdata(f"mode{j}", "Hz"),
            )
        except LumApiError:
            break
        modes.append(mode)

    modes = sorted(modes, key=lambda m: np.real(m.neff), reverse=True)
    return post_process(modes)

compute_modes_tidy3d

compute_modes_tidy3d(
    cs: CrossSection,
    num_modes: PositiveInt = 10,
    target_neff: PositiveFloat | None = None,
    precision: Literal["single", "double"] = "double",
    post_process: Callable = post_process_modes,
) -> Modes

Compute Modes for a given CrossSection.

Source code in src/meow/fde/tidy3d.py
def compute_modes_tidy3d(
    cs: CrossSection,
    num_modes: PositiveInt = 10,
    target_neff: PositiveFloat | None = None,
    precision: Literal["single", "double"] = "double",
    post_process: Callable = post_process_modes,
) -> Modes:
    """Compute ``Modes`` for a given ``CrossSection``."""
    if num_modes < 1:
        msg = "You need to request at least 1 mode."
        raise ValueError(msg)

    od = np.zeros_like(cs.nx)  # off diagonal entry
    eps_cross = [cs.nx**2, od, od, od, cs.ny**2, od, od, od, cs.nz**2]

    if np.isinf(cs.mesh.bend_radius) or np.isnan(cs.mesh.bend_radius):
        bend_radius = None
        bend_axis = None
    else:
        bend_radius = cs.mesh.bend_radius
        bend_axis = cs.mesh.bend_axis

    mode_spec = SimpleNamespace(  # tidy3d.ModeSpec alternative (prevents type checking)
        num_modes=num_modes,
        target_neff=target_neff,
        num_pml=cs.mesh.num_pml,
        filter_pol=None,
        angle_theta=cs.mesh.angle_theta,
        angle_phi=cs.mesh.angle_phi,
        bend_radius=bend_radius,
        precision=precision,
        bend_axis=bend_axis,
        track_freq="central",
        group_index_step=False,
    )

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore", message=".*Input has data type int64.*")
        warnings.filterwarnings("ignore", message=".*divide by zero.*")
        warnings.filterwarnings("ignore", message=".*overflow encountered.*")
        warnings.filterwarnings("ignore", message=".*invalid value.*")
        ((Ex, Ey, Ez), (Hx, Hy, Hz)), neffs = (
            x.squeeze()
            for x in _compute_modes(
                eps_cross=eps_cross,
                coords=[cs.mesh.x, cs.mesh.y],
                freq=c / (cs.env.wl * 1e-6),
                mode_spec=mode_spec,
                precision=precision,
                plane_center=cs.mesh.plane_center,
            )[:2]
        )

    if num_modes == 1:
        modes = [
            Mode(
                cs=cs,
                Ex=Ex,
                Ey=Ey,
                Ez=Ez,
                Hx=Hx,
                Hy=Hy,
                Hz=Hz,
                neff=np.asarray(neffs, dtype=np.complex128).item(),
            )
            for _ in range(num_modes)
        ]
    else:  # num_modes > 1
        modes = [
            Mode(
                cs=cs,
                Ex=Ex[..., i],
                Ey=Ey[..., i],
                Ez=Ez[..., i],
                Hx=Hx[..., i],
                Hy=Hy[..., i],
                Hz=Hz[..., i],
                neff=neffs[i],
            )
            for i in range(num_modes)
        ]

    modes = sorted(modes, key=lambda m: float(np.real(m.neff)), reverse=True)
    return post_process(modes)

compute_propagation_s_matrices

compute_propagation_s_matrices(
    modes: list[Modes],
    cells: list[Cell],
    *,
    cell_lengths: list[float] | None = None,
) -> dict[str, SDictMM]

Return the propagation S-matrix for every cell in a stack.

Parameters:

Name Type Description Default
modes list[Modes]

Modal basis for each cell.

required
cells list[Cell]

Cells through which the modes propagate.

required
cell_lengths list[float] | None

Optional explicit lengths. If omitted, they are derived from cell.length.

None
Source code in src/meow/eme/propagation.py
def compute_propagation_s_matrices(
    modes: list[Modes],
    cells: list[Cell],
    *,
    cell_lengths: list[float] | None = None,
) -> dict[str, sax.SDictMM]:
    """Return the propagation S-matrix for every cell in a stack.

    Args:
        modes: Modal basis for each cell.
        cells: Cells through which the modes propagate.
        cell_lengths: Optional explicit lengths. If omitted, they are derived
            from ``cell.length``.
    """
    if cell_lengths is None:
        if cells is None:
            msg = "Either cells or cell_lengths must be provided."
            raise ValueError(msg)
        if len(cells) != len(modes):
            msg = f"len(cells) != len(modes): {len(cells)} != {len(modes)}"
            raise ValueError(msg)
        cell_lengths = [cell.length for cell in cells]

    if len(cell_lengths) != len(modes):
        msg = f"len(cell_lengths) != len(modes): {len(cell_lengths)} != {len(modes)}"
        raise ValueError(msg)

    return {
        f"p_{i}": compute_propagation_s_matrix(modes_, cell_length=cell_length)
        for i, (modes_, cell_length) in enumerate(zip(modes, cell_lengths, strict=True))
    }

compute_propagation_s_matrix

compute_propagation_s_matrix(
    modes: Modes, cell_length: float
) -> SDictMM

Return the diagonal propagation S-matrix for one cell.

Each mode acquires a phase exp(2j * pi * neff / wl * cell_length) while propagating through the cell. Backward propagation is mirrored by the bidirectional port mapping in the returned SAX dictionary.

Source code in src/meow/eme/propagation.py
def compute_propagation_s_matrix(modes: Modes, cell_length: float) -> sax.SDictMM:
    """Return the diagonal propagation S-matrix for one cell.

    Each mode acquires a phase ``exp(2j * pi * neff / wl * cell_length)`` while
    propagating through the cell. Backward propagation is mirrored by the
    bidirectional port mapping in the returned SAX dictionary.
    """
    s_dict = {
        (f"left@{i}", f"right@{i}"): jnp.exp(
            2j * jnp.pi * mode.neff / mode.env.wl * cell_length
        )
        for i, mode in enumerate(modes)
    }
    return {**s_dict, **{(p2, p1): v for (p1, p2), v in s_dict.items()}}

compute_s_matrix_sax

compute_s_matrix_sax(
    modes: list[Modes],
    *,
    cells: list[Cell] | None = None,
    cell_lengths: list[float] | None = None,
    sax_backend: Backend = "klu",
    interfaces_fn: Callable = compute_interface_s_matrices,
    propagations_fn: Callable = compute_propagation_s_matrices,
    **_: Any,
) -> SDenseMM

Calculate the S-matrix for given sets of modes.

Source code in src/meow/eme/cascade.py
def compute_s_matrix_sax(
    modes: list[Modes],
    *,
    cells: list[Cell] | None = None,
    cell_lengths: list[float] | None = None,
    sax_backend: sax.Backend = "klu",
    interfaces_fn: Callable = compute_interface_s_matrices,
    propagations_fn: Callable = compute_propagation_s_matrices,
    **_: Any,
) -> sax.SDenseMM:
    """Calculate the S-matrix for given sets of modes."""
    propagations = propagations_fn(modes, cells, cell_lengths=cell_lengths)
    interfaces = interfaces_fn(modes)
    net = _get_netlist(propagations, interfaces)
    _, analyze_fn, evaluate_fn = circuit_backends[sax_backend]  # type: ignore[reportArgumentType]
    # TODO: use analyze_instances instead of manually converting to scoo ?
    net["instances"] = {k: sax.scoo(v) for k, v in net["instances"].items()}
    analyzed = analyze_fn(net["instances"], net["nets"], net["ports"])
    S, port_map = sax.sdense(
        evaluate_fn(
            analyzed,
            instances=net["instances"],
        )
    )
    S = np.asarray(S)

    # final sorting of result:
    current_port_map = {
        (p, int(i)): j
        for (p, i), j in {
            tuple(pm.split("@")): idx for pm, idx in port_map.items()
        }.items()
    }
    desired_port_map = {pm: i for i, pm in enumerate(sorted(current_port_map))}
    idxs = [current_port_map[pm] for pm in desired_port_map]
    S = S[idxs, :][:, idxs]
    port_map = {f"{p}@{m}": v for (p, m), v in desired_port_map.items()}

    return cast(sax.SDenseMM, (S, port_map))

create_cells

create_cells(
    structures: list[Structure3D],
    mesh: Mesh2D | list[Mesh2D],
    Ls: Annotated[NDArray, Dim(1), DType("float64")],
    z_min: float = 0.0,
) -> list[Cell]

Create multiple Cell objects with a Mesh and a collection of cell lengths.

Source code in src/meow/cell.py
def create_cells(
    structures: list[Structure3D],
    mesh: Mesh2D | list[Mesh2D],
    Ls: Annotated[NDArray, Dim(1), DType("float64")],
    z_min: float = 0.0,
) -> list[Cell]:
    """Create multiple `Cell` objects with a `Mesh` and a collection of cell lengths."""
    Ls = np.asarray(Ls, float)
    if Ls.ndim != 1:
        msg = f"Ls should be 1D. Got shape: {Ls.shape}."
        raise ValueError(msg)
    if Ls.shape[0] < 0:
        msg = f"length of Ls array should be nonzero. Got: {Ls}."
        raise ValueError(msg)

    meshes = [mesh] * Ls.shape[0] if isinstance(mesh, Mesh2D) else mesh
    if len(Ls) != len(meshes):
        msg = (
            "Number of meshes should correspond to number of lengths (length of Ls). "
            f"Got {len(meshes)} != {len(Ls)}."
        )
        raise ValueError(msg)

    z = np.cumsum(np.concatenate([np.asarray([z_min], float), Ls]))
    cells = [
        Cell(
            structures=structures,
            mesh=mesh,
            z_min=z_min,
            z_max=z_max,
        )
        for mesh, (z_min, z_max) in zip(meshes, pairwise(z), strict=False)
    ]

    return cells

create_lumerical_geometries

create_lumerical_geometries(
    sim: Sim,
    structures: list[Structure3D],
    env: Environment,
    unit: float,
) -> None

Create Lumerical geometries from a list of structures.

Source code in src/meow/fde/lumerical.py
def create_lumerical_geometries(
    sim: Sim,
    structures: list[Structure3D],
    env: Environment,
    unit: float,
) -> None:
    """Create Lumerical geometries from a list of structures."""
    sim = get_sim(sim=sim)
    sim.switchtolayout()
    sim.deleteall()
    for s in structures:
        s._lumadd(sim, env, unit, "yzx")

downselect_s

downselect_s(S: SDenseMM, ports: list[str]) -> SDenseMM

Downselect the S-matrix to the given ports.

Source code in src/meow/eme/cascade.py
def downselect_s(S: sax.SDenseMM, ports: list[str]) -> sax.SDenseMM:
    """Downselect the S-matrix to the given ports."""
    S_matrix, port_map = S
    idxs = [port_map[port] for port in ports]
    S_matrix = S_matrix[idxs, :][:, idxs]
    port_map = {port: i for i, port in enumerate(ports)}
    return S_matrix, port_map

electric_energy

electric_energy(mode: Mode) -> float

Get the electric energy contained in a Mode.

Source code in src/meow/mode.py
def electric_energy(mode: Mode) -> float:
    """Get the electric energy contained in a `Mode`."""
    return electric_energy_density(mode).sum()

electric_energy_density

electric_energy_density(
    mode: Mode,
) -> ndarray[tuple[int, int], dtype[float64]]

Get the electric energy density contained in a Mode.

Source code in src/meow/mode.py
def electric_energy_density(
    mode: Mode,
) -> np.ndarray[tuple[int, int], np.dtype[np.float64]]:
    """Get the electric energy density contained in a `Mode`."""
    epsx, epsy, epsz = mode.cs.nx**2, mode.cs.ny**2, mode.cs.nz**2
    return np.real(
        0.5
        * eps0
        * (
            epsx * np.abs(mode.Ex) ** 2
            + epsy * np.abs(mode.Ey) ** 2
            + epsz * np.abs(mode.Ez) ** 2
        )
    )

energy

energy(mode: Mode) -> float

Get the energy contained in a Mode.

Source code in src/meow/mode.py
def energy(mode: Mode) -> float:
    """Get the energy contained in a `Mode`."""
    return energy_density(mode).sum()

energy_density

energy_density(
    mode: Mode,
) -> ndarray[tuple[int, int], dtype[float64]]

Get the energy density contained in a Mode.

Source code in src/meow/mode.py
def energy_density(mode: Mode) -> np.ndarray[tuple[int, int], np.dtype[np.float64]]:
    """Get the energy density contained in a `Mode`."""
    return electric_energy_density(mode) + magnetic_energy_density(mode)

enforce_passivity

enforce_passivity(
    singular_values: ndarray,
    *,
    method: PassivityMethod = "invert",
) -> ndarray

Project singular values onto a passive interval.

This function post-processes the singular values of an S-matrix so that the resulting matrix has singular values no larger than one.

Available methods
  • "none": leave the singular values unchanged.
  • "clip": replace values larger than one by exactly one.
  • "invert": replace sigma by 1 / sigma when sigma > 1.
  • "subtract": replace sigma by max(0, 2 - sigma) when sigma > 1.
High-level interpretation

clip is the most conservative algebraic projection. invert and subtract both map modest gain above one to modest loss below one, which can be useful when the excess gain is interpreted as missing radiation channels in a truncated basis.

Sharp edge

These are heuristic corrections on top of a truncated modal solve. They are often useful, but they are not substitutes for a converged basis.

Parameters:

Name Type Description Default
singular_values ndarray

Singular values to correct.

required
method PassivityMethod

Passivity enforcement strategy.

'invert'

Returns:

Type Description
ndarray

Corrected singular values.

Raises:

Type Description
ValueError

If method is unknown.

Source code in src/meow/eme/interface.py
def enforce_passivity(
    singular_values: np.ndarray, *, method: PassivityMethod = "invert"
) -> np.ndarray:
    """Project singular values onto a passive interval.

    This function post-processes the singular values of an S-matrix so that the
    resulting matrix has singular values no larger than one.

    Available methods:
        - ``"none"``: leave the singular values unchanged.
        - ``"clip"``: replace values larger than one by exactly one.
        - ``"invert"``: replace ``sigma`` by ``1 / sigma`` when ``sigma > 1``.
        - ``"subtract"``: replace ``sigma`` by ``max(0, 2 - sigma)`` when
          ``sigma > 1``.

    High-level interpretation:
        ``clip`` is the most conservative algebraic projection. ``invert`` and
        ``subtract`` both map modest gain above one to modest loss below one,
        which can be useful when the excess gain is interpreted as missing
        radiation channels in a truncated basis.

    Sharp edge:
        These are heuristic corrections on top of a truncated modal solve. They
        are often useful, but they are not substitutes for a converged basis.

    Args:
        singular_values: Singular values to correct.
        method: Passivity enforcement strategy.

    Returns:
        Corrected singular values.

    Raises:
        ValueError: If ``method`` is unknown.
    """
    match method:
        case "none":
            return singular_values
        case "clip":
            return np.where(singular_values > 1.0, 1.0, singular_values)
        case "invert":
            return np.where(singular_values > 1.0, 1 / singular_values, singular_values)
        case "subtract":
            singular_values = np.where(
                singular_values > 1.0, 2.0 - singular_values, singular_values
            )
            return np.where(singular_values < 0.0, 0.0, singular_values)
        case _:
            msg = f"Unknown passivity enforcement method {method}."
            raise ValueError(msg)

extrude_gds

extrude_gds(
    cell: Any,
    extrusions: dict[
        tuple[int, int], list[GdsExtrusionRule]
    ],
) -> list[Structure3D]

Extrude a gds cell given a dictionary of extruson rules.

Parameters:

Name Type Description Default
cell Any

a gdspy or gdstk Cell to extrude

required
extrusions dict[tuple[int, int], list[GdsExtrusionRule]]

the extrusion rules to use (if not given, the example extrusions will be used.)

required
Source code in src/meow/gds_structures.py
def extrude_gds(
    cell: Any,  # gf.Component | gdspy.Cell | gdstk.Cell
    extrusions: dict[tuple[int, int], list[GdsExtrusionRule]],
) -> list[Structure3D]:
    """Extrude a gds cell given a dictionary of extruson rules.

    Args:
        cell: a gdspy or gdstk Cell to extrude
        extrusions: the extrusion rules to use
            (if not given, the example extrusions will be used.)
    """
    structs = []
    for layer, polys in _get_polygons(cell).items():
        for poly in polys:
            if layer not in extrusions:
                continue
            structs.extend(extrusion(poly) for extrusion in extrusions[layer])
    return structs

filter_modes

filter_modes(
    modes: Modes,
    conditions: Iterable[Callable] = (
        is_pml_mode,
        is_lossy_mode,
    ),
) -> Modes

Filter a set of modes according to certain criteria.

Parameters:

Name Type Description Default
modes Modes

the list of modes to filter

required
conditions Iterable[Callable]

the conditions to filter the modes with

(is_pml_mode, is_lossy_mode)

Returns:

Type Description
Modes

the filtered modes

Source code in src/meow/fde/post_process.py
def filter_modes(
    modes: Modes,
    conditions: Iterable[Callable] = (is_pml_mode, is_lossy_mode),
) -> Modes:
    """Filter a set of modes according to certain criteria.

    Args:
        modes: the list of modes to filter
        conditions: the conditions to filter the modes with

    Returns:
        the filtered modes
    """
    kept = []
    for mode in modes:
        for condition_fn in conditions:
            if condition_fn(mode):
                break
        else:
            kept.append(mode)
    return kept

get_sim

get_sim(**kwargs: Any) -> Sim

Get the Lumerical simulation object.

Source code in src/meow/fde/lumerical.py
def get_sim(**kwargs: Any) -> Sim:
    """Get the Lumerical simulation object."""
    global _sim  # noqa: PLW0603
    sim = kwargs.get("sim", None)
    if sim is not None:
        _sim = sim
        return sim
    sim = _sim
    if sim is None:
        msg = (
            "Could not start Lumerical simulation. Please either pass the "
            "`lumapi.MODE` simulation object as an argument to "
            "`compute_modes_lumerical` to globally "
            "set the lumapi.MODE simulation object."
        )
        raise ValueError(msg)
    return sim

inner_product

inner_product(
    mode1: Mode,
    mode2: Mode,
    *,
    symmetric: bool = False,
    conjugate: bool = False,
    ignore_pml: bool = True,
    interpolation: Literal[
        "Ex", "Ey", "Ez", "Hx", "Hy", "Hz"
    ]
    | None = None,
) -> complex

The modal inner product for z-normal mode planes.

Parameters:

Name Type Description Default
mode1 Mode

the left mode

required
mode2 Mode

the right mode

required
symmetric bool

use the symmetric inner product definition

False
conjugate bool

use the conjugage inner product definition (power normalization)

False
ignore_pml bool

ignore PML region while taking the inner product

True
interpolation Literal['Ex', 'Ey', 'Ez', 'Hx', 'Hy', 'Hz'] | None

interpolate both modes to a certain field-grid position before taking the inner product.

None

Returns:

Type Description
complex

the inner product

Source code in src/meow/mode.py
def inner_product(
    mode1: Mode,
    mode2: Mode,
    *,
    symmetric: bool = False,
    conjugate: bool = False,
    ignore_pml: bool = True,
    interpolation: Literal["Ex", "Ey", "Ez", "Hx", "Hy", "Hz"] | None = None,
) -> complex:
    """The modal inner product for z-normal mode planes.

    Args:
        mode1: the left mode
        mode2: the right mode
        symmetric: use the symmetric inner product definition
        conjugate: use the conjugage inner product definition (power normalization)
        ignore_pml: ignore PML region while taking the inner product
        interpolation: interpolate both modes to a certain field-grid position
            before taking the inner product.

    Returns:
        the inner product
    """
    mode1 = mode1.interpolate(interpolation)
    mode2 = mode2.interpolate(interpolation)

    mesh = mode1.mesh
    x = np.asarray(mesh.x_)
    y = np.asarray(mesh.y_)

    if conjugate:
        ex1, ey1 = mode1.Ex.conj(), mode1.Ey.conj()
        hx1, hy1 = mode1.Hx.conj(), mode1.Hy.conj()
    else:
        ex1, ey1 = mode1.Ex, mode1.Ey
        hx1, hy1 = mode1.Hx, mode1.Hy

    e1_cross_h2 = ex1 * mode2.Hy - ey1 * mode2.Hx
    if symmetric:
        h1_cross_e2 = hx1 * mode2.Ey - hy1 * mode2.Ex
        integrand = 0.25 * (e1_cross_h2 - h1_cross_e2)
    else:
        integrand = 0.5 * e1_cross_h2

    if ignore_pml:
        integrand, x, y = _crop_non_pml(mesh, integrand, x, y)

    arr = np.trapezoid(np.trapezoid(integrand, y), x)
    return float(np.real(arr)) + float(np.imag(arr)) * 1j

invert_mode

invert_mode(mode: Mode) -> Mode

Invert a Mode.

Source code in src/meow/mode.py
def invert_mode(mode: Mode) -> Mode:
    """Invert a `Mode`."""
    return Mode(
        neff=mode.neff,
        cs=mode.cs,
        Ex=-mode.Ex,
        Ey=-mode.Ey,
        Ez=-mode.Ez,
        Hx=-mode.Hx,
        Hy=-mode.Hy,
        Hz=-mode.Hz,
    )

is_lossy_mode

is_lossy_mode(
    mode: Mode, *, threshold: float = 1.0
) -> bool

Check whether a mode can be considered lossy.

Source code in src/meow/mode.py
def is_lossy_mode(mode: Mode, *, threshold: float = 1.0) -> bool:
    """Check whether a mode can be considered lossy."""
    return bool(abs(np.imag(mode.neff)) > threshold)

is_pml_mode

is_pml_mode(mode: Mode, *, threshold: float = 0.1) -> bool

Check whether a mode can be considered a PML mode.

Source code in src/meow/mode.py
def is_pml_mode(mode: Mode, *, threshold: float = 0.1) -> bool:
    """Check whether a mode can be considered a PML mode."""
    threshold = min(max(float(threshold), 0.0), 1.0)
    if threshold > 0.999:
        return False
    return abs(pml_fraction(mode)) > threshold

l2r_matrices

l2r_matrices(
    pairs: list[STypeMM],
    identity: SDenseMM,
    sax_backend: Backend,
) -> list[STypeMM]

Return cumulative left-to-right S-matrices.

Source code in src/meow/eme/propagation.py
def l2r_matrices(
    pairs: list[sax.STypeMM], identity: sax.SDenseMM, sax_backend: sax.Backend
) -> list[sax.STypeMM]:
    """Return cumulative left-to-right S-matrices."""
    matrices: list[sax.STypeMM] = [identity]
    for pair in pairs[:-1]:
        matrices.append(_connect_two(matrices[-1], pair, sax_backend))
    return matrices

magnetic_energy

magnetic_energy(mode: Mode) -> float

Get the magnetic energy contained in a Mode.

Source code in src/meow/mode.py
def magnetic_energy(mode: Mode) -> float:
    """Get the magnetic energy contained in a `Mode`."""
    return magnetic_energy_density(mode).sum()

magnetic_energy_density

magnetic_energy_density(
    mode: Mode,
) -> ndarray[tuple[int, int], dtype[float64]]

Get the magnetic energy density contained in a Mode.

Source code in src/meow/mode.py
def magnetic_energy_density(
    mode: Mode,
) -> np.ndarray[tuple[int, int], np.dtype[np.float64]]:
    """Get the magnetic energy density contained in a `Mode`."""
    return np.real(
        0.5 * mu0 * (np.abs(mode.Hx) ** 2 + np.abs(mode.Hy) ** 2 + np.abs(mode.Hz) ** 2)
    )

normalize

normalize(mode: Mode, inner_product: Callable) -> Mode

Normalize a Mode according to the inner_product with itself.

Source code in src/meow/mode.py
def normalize(mode: Mode, inner_product: Callable) -> Mode:
    """Normalize a `Mode` according to the `inner_product` with itself."""
    factor = np.sqrt(inner_product(mode, mode))
    return Mode(
        neff=mode.neff,
        cs=mode.cs,
        Ex=mode.Ex / factor,
        Ey=mode.Ey / factor,
        Ez=mode.Ez / factor,
        Hx=mode.Hx / factor,
        Hy=mode.Hy / factor,
        Hz=mode.Hz / factor,
    )

normalize_energy

normalize_energy(mode: Mode) -> Mode

Normalize a mode according to the energy it contains.

Source code in src/meow/mode.py
def normalize_energy(mode: Mode) -> Mode:
    """Normalize a mode according to the energy it contains."""
    e = np.sqrt(2 * electric_energy(mode))
    h = np.sqrt(2 * magnetic_energy(mode))

    return Mode(
        neff=mode.neff,
        cs=mode.cs,
        Ex=mode.Ex / e,
        Ey=mode.Ey / e,
        Ez=mode.Ez / e,
        Hx=mode.Hx / h,
        Hy=mode.Hy / h,
        Hz=mode.Hz / h,
    )

normalize_modes

normalize_modes(
    modes: Modes, inner_product: Callable
) -> Modes

Self-normalize a set of modes.

This only fixes the norm of each mode individually. It does not make the mode set mutually orthogonal. For overlap-based interface formulas, use :func:orthonormalize_modes if you need the simplified G = I metric.

Source code in src/meow/fde/post_process.py
def normalize_modes(modes: Modes, inner_product: Callable) -> Modes:
    """Self-normalize a set of modes.

    This only fixes the norm of each mode individually. It does not make the
    mode set mutually orthogonal. For overlap-based interface formulas, use
    :func:`orthonormalize_modes` if you need the simplified ``G = I`` metric.
    """
    return [zero_phase(normalize(m, inner_product)) for m in modes]

orthonormalize_modes

orthonormalize_modes(
    modes: Modes,
    inner_product: Callable,
    *,
    tolerance: float = 0.01,
) -> Modes

Gram-Schmidt orthonormalization with drop tolerance.

Parameters:

Name Type Description Default
modes Modes

the modes to orthonormalize

required
inner_product Callable

the inner product to orthonormalize them under

required
tolerance float

any mode that can't expand the basis beyond this tolerance will be dropped.

0.01

Returns:

Type Description
Modes

Orthonormalized mode basis.

Notes

This routine first self-normalizes each mode and then applies Gram-Schmidt. The inner_product passed here should generally be the same one used later to build interface overlaps; otherwise the final basis is orthonormal in the wrong metric.

Source code in src/meow/fde/post_process.py
def orthonormalize_modes(
    modes: Modes,
    inner_product: Callable,
    *,
    tolerance: float = 0.01,
) -> Modes:
    """Gram-Schmidt orthonormalization with drop tolerance.

    Args:
        modes: the modes to orthonormalize
        inner_product: the inner product to orthonormalize them under
        tolerance: any mode that can't expand the basis beyond this tolerance
            will be dropped.

    Returns:
        Orthonormalized mode basis.

    Notes:
        This routine first self-normalizes each mode and then applies
        Gram-Schmidt. The ``inner_product`` passed here should generally be the
        same one used later to build interface overlaps; otherwise the final
        basis is orthonormal in the wrong metric.
    """
    if not modes:
        return []
    modes = normalize_modes(modes, inner_product)
    basis = []
    n_dropped = 0
    for mode in modes:
        current = mode
        for b in basis:
            current = current - (inner_product(b, current) / inner_product(b, b)) * b
        norm_sq = inner_product(current, current)
        if abs(norm_sq) < tolerance:
            n_dropped += 1
            continue
        basis.append(current / np.sqrt(norm_sq))
    return basis

overlap_matrix

overlap_matrix(
    modes1: Modes, modes2: Modes, inner_product: Callable
) -> ndarray[tuple[int, int], dtype[complex128]]

Build the modal overlap matrix between two mode sets.

The entry M[i, j] is inner_product(modes1[i], modes2[j]). In the interface derivation this is used both for self-overlaps (the metric G) and cross-overlaps between the left and right waveguide bases.

Sharp edge

The meaning of the overlap matrix is entirely determined by the inner_product callable. If modes were orthonormalized with one inner product but overlaps are formed with another, the simplified G = I interface formulas are no longer valid.

Parameters:

Name Type Description Default
modes1 Modes

Left/test mode set.

required
modes2 Modes

Right/expansion mode set.

required
inner_product Callable

Modal inner-product callable.

required

Returns:

Type Description
ndarray[tuple[int, int], dtype[complex128]]

Complex overlap matrix of shape (len(modes1), len(modes2)).

Source code in src/meow/eme/interface.py
def overlap_matrix(
    modes1: Modes, modes2: Modes, inner_product: Callable
) -> np.ndarray[tuple[int, int], np.dtype[np.complex128]]:
    """Build the modal overlap matrix between two mode sets.

    The entry ``M[i, j]`` is ``inner_product(modes1[i], modes2[j])``. In the
    interface derivation this is used both for self-overlaps (the metric ``G``)
    and cross-overlaps between the left and right waveguide bases.

    Sharp edge:
        The meaning of the overlap matrix is entirely determined by the
        ``inner_product`` callable. If modes were orthonormalized with one
        inner product but overlaps are formed with another, the simplified
        ``G = I`` interface formulas are no longer valid.

    Args:
        modes1: Left/test mode set.
        modes2: Right/expansion mode set.
        inner_product: Modal inner-product callable.

    Returns:
        Complex overlap matrix of shape ``(len(modes1), len(modes2))``.
    """
    M = np.zeros((len(modes1), len(modes2)), dtype=np.complex128)
    for i, ma in enumerate(modes1):
        for j, mb in enumerate(modes2):
            M[i, j] = inner_product(ma, mb)
    return M

pi_pairs

pi_pairs(
    propagations: dict[str, SDictMM],
    interfaces: dict[str, SDenseMM],
    sax_backend: Backend,
) -> list[STypeMM]

Return propagation-interface pairs for a full stack.

Source code in src/meow/eme/propagation.py
def pi_pairs(
    propagations: dict[str, sax.SDictMM],
    interfaces: dict[str, sax.SDenseMM],
    sax_backend: sax.Backend,
) -> list[sax.STypeMM]:
    """Return propagation-interface pairs for a full stack."""
    pairs: list[sax.STypeMM] = []
    for i in range(len(propagations)):
        propagation = propagations[f"p_{i}"]
        if i == len(interfaces):
            pairs.append(propagation)
        else:
            pairs.append(
                _connect_two(propagation, interfaces[f"i_{i}_{i + 1}"], sax_backend)
            )
    return pairs

plot_fields

plot_fields(
    modes: list[list[Mode]],
    cells: list[Cell],
    forwards: list[ComplexArray1D],
    backwards: list[ComplexArray1D],
    y: float,
    z: FloatArray1D,
) -> tuple[ComplexArray2D, FloatArray1D]

Reconstruct an Ex(x, z) field slice from propagated modal amplitudes.

Source code in src/meow/eme/propagation.py
def plot_fields(
    modes: list[list[Mode]],
    cells: list[Cell],
    forwards: list[ComplexArray1D],
    backwards: list[ComplexArray1D],
    y: float,
    z: FloatArray1D,
) -> tuple[ComplexArray2D, FloatArray1D]:
    """Reconstruct an ``Ex(x, z)`` field slice from propagated modal amplitudes."""
    mesh_y = cells[0].mesh.y
    mesh_x = cells[0].mesh.x
    mesh_x = mesh_x[:-1] + np.diff(mesh_x) / 2
    i_y = np.argmin(np.abs(mesh_y - y))

    e_tot = np.zeros((len(z), len(mesh_x)), dtype=complex)
    for mode_set, forward, backward, cell in zip(
        modes, forwards, backwards, cells, strict=False
    ):
        ex = np.array(0 + 0j)
        i_min = np.argmax(z >= cell.z_min)
        i_max = np.argmax(z > cell.z_max)
        z_ = z[i_min:] if i_max == 0 else z[i_min:i_max]
        z_local = z_ - cell.z_min
        for mode, fwd, bwd in zip(mode_set, forward, backward, strict=False):
            e_slice = mode.Ex[:, i_y]
            ex += jnp.outer(
                fwd * e_slice.T, jnp.exp(2j * np.pi * mode.neff / mode.env.wl * z_local)
            )
            ex += jnp.outer(
                bwd * e_slice.T,
                jnp.exp(-2j * np.pi * mode.neff / mode.env.wl * z_local),
            )

        if i_max == 0:
            e_tot[i_min:] = ex.T
        else:
            e_tot[i_min:i_max] = ex.T

    return e_tot, mesh_x

pml_fraction

pml_fraction(mode: Mode) -> float

Fraction of energy density in the PML region.

Source code in src/meow/mode.py
def pml_fraction(mode: Mode) -> float:
    """Fraction of energy density in the PML region."""
    numx, numy = mode.mesh.num_pml
    if numx == numy == 0:
        return 0.0
    ed = energy_density(mode)
    m, n = ed.shape
    lft = ed[:numx, :]
    rgt = ed[m - numx :, :]
    top = ed[numx : m - numx, :numy]
    btm = ed[numx : m - numx, n - numy :]
    rest = ed[numx : m - numx, numy : n - numy]
    pml_sum = lft.sum() + rgt.sum() + top.sum() + btm.sum()
    total = pml_sum + rest.sum()
    # probably propper integration considering
    # the size of the mesh cells would be better here
    return float(pml_sum / total) if total > 0 else 1.0

post_process_modes

post_process_modes(
    modes: Modes,
    inner_product: Callable = inner_product,
    gm_tolerance: float = 0.01,
) -> Modes

Default post-processing pipeline after FDE.

Parameters:

Name Type Description Default
modes Modes

the modes to post process

required
inner_product Callable

the inner product with which to post-process the modes

inner_product
gm_tolerance float

Gramm-Schmidt orthonormalization tolerance

0.01

Returns:

Type Description
Modes

Filtered and orthonormalized modes.

Notes

This is the default post_process used by compute_modes. The choice of inner_product here matters downstream: if interface overlaps are later built with a different inner product, the resulting mode basis is no longer orthonormal in the interface metric.

Source code in src/meow/fde/post_process.py
def post_process_modes(
    modes: Modes,
    inner_product: Callable = inner_product,
    gm_tolerance: float = 0.01,
) -> Modes:
    """Default post-processing pipeline after FDE.

    Args:
        modes: the modes to post process
        inner_product: the inner product with which to post-process the modes
        gm_tolerance: Gramm-Schmidt orthonormalization tolerance

    Returns:
        Filtered and orthonormalized modes.

    Notes:
        This is the default ``post_process`` used by ``compute_modes``. The
        choice of ``inner_product`` here matters downstream: if interface
        overlaps are later built with a different inner product, the resulting
        mode basis is no longer orthonormal in the interface metric.
    """
    return orthonormalize_modes(
        filter_modes(modes),
        inner_product,
        tolerance=gm_tolerance,
    )

propagate

propagate(
    l2rs: list[STypeMM],
    r2ls: list[STypeMM],
    excitation_l: ComplexArray1D,
    excitation_r: ComplexArray1D,
) -> tuple[list[ComplexArray1D], list[ComplexArray1D]]

Propagate boundary excitations through cumulative S-matrices.

Source code in src/meow/eme/propagation.py
def propagate(
    l2rs: list[sax.STypeMM],
    r2ls: list[sax.STypeMM],
    excitation_l: ComplexArray1D,
    excitation_r: ComplexArray1D,
) -> tuple[list[ComplexArray1D], list[ComplexArray1D]]:
    """Propagate boundary excitations through cumulative S-matrices."""
    forwards = []
    backwards = []
    for l2r, r2l in zip(l2rs, r2ls, strict=False):
        s_l2r, pm_l2r = sax.sdense(l2r)
        s_r2l, pm_r2l = sax.sdense(r2l)
        ports_l2r = _sorted_ports(pm_l2r)
        ports_r2l = _sorted_ports(pm_r2l)
        s_l2r, _ = select_ports((s_l2r, pm_l2r), ports_l2r)
        s_r2l, _ = select_ports((s_r2l, pm_r2l), ports_r2l)
        n_right = len([key for key in ports_l2r if "right" in key])
        fwd, bwd = compute_mode_amplitudes(
            np.asarray(s_l2r), np.asarray(s_r2l), n_right, excitation_l, excitation_r
        )
        forwards.append(fwd)
        backwards.append(bwd)
    return forwards, backwards

propagate_modes

propagate_modes(
    modes: list[list[Mode]],
    cells: list[Cell],
    *,
    excitation_l: ComplexArray1D | None = None,
    excitation_r: ComplexArray1D | None = None,
    excite_mode_l: int = 0,
    excite_mode_r: int | None = None,
    y: float | None = None,
    z: FloatArray1D | None = None,
    num_z: int = 1000,
    sax_backend: BackendLike = "default",
    interface_kwargs: dict[str, Any] | None = None,
    track: bool = True,
    tracking_inner_product: Callable = inner_product,
    interfaces_fn: Callable = compute_interface_s_matrices,
    interface_fn: Callable = compute_interface_s_matrix,
) -> tuple[ComplexArray2D, FloatArray1D]

Propagate modal excitations through a stack of cells.

This is a convenience wrapper around the propagation and interface S-matrix machinery. The only required positional inputs are the modal bases and the cells. Everything else has defaults that are inferred from the stack:

  • by default the left boundary excites mode 0 with unit amplitude;
  • by default there is no right-side excitation;
  • by default y is the center of the transverse mesh;
  • by default z spans the full device with num_z samples.

Parameters:

Name Type Description Default
modes list[list[Mode]]

Mode set for each cell.

required
cells list[Cell]

Cells associated with modes.

required
excitation_l ComplexArray1D | None

Optional explicit left excitation vector.

None
excitation_r ComplexArray1D | None

Optional explicit right excitation vector.

None
excite_mode_l int

Left mode to excite if excitation_l is omitted.

0
excite_mode_r int | None

Right mode to excite if excitation_r is omitted. If omitted, no right-side excitation is applied.

None
y float | None

Transverse y-coordinate at which to reconstruct Ex.

None
z FloatArray1D | None

Global z-grid on which to reconstruct the field.

None
num_z int

Number of z samples if z is omitted.

1000
sax_backend BackendLike

SAX backend used for cascading.

'default'
interface_kwargs dict[str, Any] | None

Optional keyword arguments forwarded to both interfaces_fn and interface_fn.

None
track bool

Whether to reorder and phase-align modes between neighboring cells before propagation.

True
tracking_inner_product Callable

Inner product used for mode tracking.

inner_product
interfaces_fn Callable

Factory for interface S-matrices across the stack.

compute_interface_s_matrices
interface_fn Callable

Factory for the identity-like same-basis interface used to seed the left-to-right accumulation.

compute_interface_s_matrix

Returns:

Type Description
ComplexArray2D

(field, x) where field is the reconstructed Ex(z, x) slice

FloatArray1D

and x is the transverse sampling grid.

Source code in src/meow/eme/propagation.py
def propagate_modes(
    modes: list[list[Mode]],
    cells: list[Cell],
    *,
    excitation_l: ComplexArray1D | None = None,
    excitation_r: ComplexArray1D | None = None,
    excite_mode_l: int = 0,
    excite_mode_r: int | None = None,
    y: float | None = None,
    z: FloatArray1D | None = None,
    num_z: int = 1000,
    sax_backend: sax.BackendLike = "default",
    interface_kwargs: dict[str, Any] | None = None,
    track: bool = True,
    tracking_inner_product: Callable = inner_product,
    interfaces_fn: Callable = compute_interface_s_matrices,
    interface_fn: Callable = compute_interface_s_matrix,
) -> tuple[ComplexArray2D, FloatArray1D]:
    """Propagate modal excitations through a stack of cells.

    This is a convenience wrapper around the propagation and interface S-matrix
    machinery. The only required positional inputs are the modal bases and the
    cells. Everything else has defaults that are inferred from the stack:

    - by default the left boundary excites mode 0 with unit amplitude;
    - by default there is no right-side excitation;
    - by default ``y`` is the center of the transverse mesh;
    - by default ``z`` spans the full device with ``num_z`` samples.

    Args:
        modes: Mode set for each cell.
        cells: Cells associated with ``modes``.
        excitation_l: Optional explicit left excitation vector.
        excitation_r: Optional explicit right excitation vector.
        excite_mode_l: Left mode to excite if ``excitation_l`` is omitted.
        excite_mode_r: Right mode to excite if ``excitation_r`` is omitted. If
            omitted, no right-side excitation is applied.
        y: Transverse y-coordinate at which to reconstruct ``Ex``.
        z: Global z-grid on which to reconstruct the field.
        num_z: Number of z samples if ``z`` is omitted.
        sax_backend: SAX backend used for cascading.
        interface_kwargs: Optional keyword arguments forwarded to both
            ``interfaces_fn`` and ``interface_fn``.
        track: Whether to reorder and phase-align modes between neighboring
            cells before propagation.
        tracking_inner_product: Inner product used for mode tracking.
        interfaces_fn: Factory for interface S-matrices across the stack.
        interface_fn: Factory for the identity-like same-basis interface used to
            seed the left-to-right accumulation.

    Returns:
        ``(field, x)`` where ``field`` is the reconstructed ``Ex(z, x)`` slice
        and ``x`` is the transverse sampling grid.
    """
    if len(cells) != len(modes):
        msg = f"len(cells) != len(modes): {len(cells)} != {len(modes)}"
        raise ValueError(msg)
    if not cells:
        msg = "At least one cell is required."
        raise ValueError(msg)

    actual_sax_backend = sax.into[sax.Backend](sax_backend)
    interface_kwargs = dict(interface_kwargs or {})
    interface_kwargs.setdefault("enforce_reciprocity", False)

    if excitation_l is None:
        excitation_l = _default_excitation(len(modes[0]), excite_mode_l)
    if excitation_r is None:
        if excite_mode_r is None:
            excitation_r = np.zeros(len(modes[-1]), dtype=complex)
        else:
            excitation_r = _default_excitation(len(modes[-1]), excite_mode_r)

    if y is None:
        y = float(0.5 * (cells[0].mesh.y.min() + cells[0].mesh.y.max()))
    if z is None:
        z = _default_z(cells, num_z)

    tracked_modes = (
        track_modes(modes, inner_product_fn=tracking_inner_product) if track else modes
    )

    propagations = compute_propagation_s_matrices(tracked_modes, cells)
    interfaces = interfaces_fn(tracked_modes, **interface_kwargs)
    identity = interface_fn(tracked_modes[0], tracked_modes[0], **interface_kwargs)

    pairs = pi_pairs(propagations, interfaces, actual_sax_backend)
    l2rs = l2r_matrices(pairs, identity, actual_sax_backend)
    r2ls = r2l_matrices(pairs, actual_sax_backend)

    forwards, backwards = propagate(l2rs, r2ls, excitation_l, excitation_r)
    return plot_fields(tracked_modes, cells, forwards, backwards, y, z)

r2l_matrices

r2l_matrices(
    pairs: list[STypeMM], sax_backend: Backend
) -> list[STypeMM]

Return cumulative right-to-left S-matrices.

Source code in src/meow/eme/propagation.py
def r2l_matrices(
    pairs: list[sax.STypeMM], sax_backend: sax.Backend
) -> list[sax.STypeMM]:
    """Return cumulative right-to-left S-matrices."""
    matrices = [pairs[-1]]
    for pair in pairs[-2::-1]:
        matrices.append(_connect_two(pair, matrices[-1], sax_backend))
    return matrices[::-1]

select_ports

select_ports(S: SDenseMM, ports: list[str]) -> SDenseMM

Keep a subset of ports from an S-matrix.

Source code in src/meow/eme/propagation.py
def select_ports(S: sax.SDenseMM, ports: list[str]) -> sax.SDenseMM:
    """Keep a subset of ports from an S-matrix."""
    s, pm = S
    idxs = jnp.array([pm[port] for port in ports], dtype=jnp.int32)
    s = s[idxs, :][:, idxs]
    new_port_map = {p: i for i, p in enumerate(ports)}
    return s, new_port_map

sort_structures

sort_structures(
    structures: list[Structure3D],
) -> list[Structure3D]
sort_structures(
    structures: list[Structure2D],
) -> list[Structure2D]
sort_structures(
    structures: list[Structure3D] | list[Structure2D],
) -> list[Structure2D] | list[Structure3D]

Sort structures by mesh order, then by order of definition.

Source code in src/meow/structures.py
def sort_structures(
    structures: list[Structure3D] | list[Structure2D],
) -> list[Structure2D] | list[Structure3D]:
    """Sort structures by mesh order, then by order of definition."""
    struct_info = [(s.mesh_order, -i, s) for i, s in enumerate(structures)]
    sorted_struct_info = sorted(struct_info, key=lambda I: (I[0], I[1]), reverse=True)
    return cast(
        list[Structure2D] | list[Structure3D], [s for _, _, s in sorted_struct_info]
    )

split_square_matrix

split_square_matrix(
    matrix: ComplexArray2D, idx: int
) -> tuple[
    tuple[ComplexArray2D, ComplexArray2D],
    tuple[ComplexArray2D, ComplexArray2D],
]

Split a square matrix into its four block submatrices.

Source code in src/meow/eme/propagation.py
def split_square_matrix(
    matrix: ComplexArray2D, idx: int
) -> tuple[
    tuple[ComplexArray2D, ComplexArray2D], tuple[ComplexArray2D, ComplexArray2D]
]:
    """Split a square matrix into its four block submatrices."""
    if matrix.shape[0] != matrix.shape[1]:
        msg = "Matrix has to be square."
        raise ValueError(msg)
    return (matrix[:idx, :idx], matrix[:idx, idx:]), (
        matrix[idx:, :idx],
        matrix[idx:, idx:],
    )

te_fraction

te_fraction(mode: Mode) -> float

The TE polarization fraction of the Mode.

Source code in src/meow/mode.py
def te_fraction(mode: Mode) -> float:
    """The TE polarization fraction of the `Mode`."""
    epsx = np.real(mode.cs.nx**2)
    e = np.sum(0.5 * eps0 * epsx * np.abs(mode.Ex) ** 2)
    h = np.sum(0.5 * mu0 * np.abs(mode.Hx) ** 2)
    return float(e / (e + h))

track_modes

track_modes(
    modes: list[Modes],
    *,
    inner_product_fn: Callable = inner_product,
) -> list[Modes]

Track modal order and phase continuously across a cell stack.

Modes are solved independently in each cell, so neighboring cells may differ by permutation and arbitrary complex phase. This helper reorders each mode set by maximum overlap with the previous cell and phase-aligns matched modes so that the tracking overlap is real-positive.

Unmatched modes are appended after the matched subset in their original order. This function does not change the physics of the interface solve; it only makes the local basis more continuous for reconstruction and plotting.

Source code in src/meow/eme/propagation.py
def track_modes(
    modes: list[Modes],
    *,
    inner_product_fn: Callable = inner_product,
) -> list[Modes]:
    """Track modal order and phase continuously across a cell stack.

    Modes are solved independently in each cell, so neighboring cells may differ
    by permutation and arbitrary complex phase. This helper reorders each mode
    set by maximum overlap with the previous cell and phase-aligns matched modes
    so that the tracking overlap is real-positive.

    Unmatched modes are appended after the matched subset in their original
    order. This function does not change the physics of the interface solve; it
    only makes the local basis more continuous for reconstruction and plotting.
    """
    if not modes:
        return []

    tracked: list[Modes] = [list(modes[0])]
    for current in modes[1:]:
        previous = tracked[-1]
        n_prev = len(previous)
        n_curr = len(current)
        if n_prev == 0 or n_curr == 0:
            tracked.append(list(current))
            continue

        overlaps = np.zeros((n_prev, n_curr), dtype=np.complex128)
        for i, mode_prev in enumerate(previous):
            for j, mode_curr in enumerate(current):
                overlaps[i, j] = inner_product_fn(mode_prev, mode_curr)

        row_ind, col_ind = linear_sum_assignment(-np.abs(overlaps))
        matched_cols = set(col_ind.tolist())

        reordered: list[Mode] = []
        for i, j in sorted(
            zip(row_ind, col_ind, strict=True), key=lambda pair: pair[0]
        ):
            overlap = overlaps[i, j]
            if np.abs(overlap) > 0:
                phase = np.exp(-1j * np.angle(overlap))
                reordered.append(current[j] * phase)
            else:
                reordered.append(current[j])

        reordered.extend(
            mode for j, mode in enumerate(current) if j not in matched_cols
        )
        tracked.append(reordered)

    return tracked

tsvd_solve

tsvd_solve(
    A: ndarray, B: ndarray, rcond: float = 0.001
) -> tuple[ndarray, ndarray, float, float]

Solve A X = B with a truncated-SVD pseudoinverse.

This is the regularized solve used by the EME interface construction. The smallest singular directions of A are the first place where truncated mode sets become numerically unstable, so the solve is performed as

X = pinv_tsvd(A) @ B

with a relative cutoff

s_cut = rcond * s_max.

Singular values below s_cut are discarded entirely.

High-level behavior
  • small rcond keeps more singular directions and is closer to the exact inverse, but is more sensitive to ill-conditioning;
  • large rcond drops more singular directions and is more stable, but biases the result towards a lower-rank approximation.

This routine does not enforce passivity by itself. It only stabilizes the linear inversion. Passivity is handled afterwards on the assembled interface S-matrix.

Parameters:

Name Type Description Default
A ndarray

System matrix to invert approximately.

required
B ndarray

Right-hand side.

required
rcond float

Relative singular-value cutoff. Singular values smaller than rcond * max(s) are discarded.

0.001

Returns:

Type Description
ndarray

A tuple (X, s, s_cut, rank_kept) containing the solved result,

ndarray

the singular values of A, the absolute cutoff, and the number of

float

retained singular directions.

Raises:

Type Description
RuntimeError

If all singular values are rejected.

Source code in src/meow/eme/solve.py
def tsvd_solve(
    A: np.ndarray, B: np.ndarray, rcond: float = 1e-3
) -> tuple[np.ndarray, np.ndarray, float, float]:
    """Solve ``A X = B`` with a truncated-SVD pseudoinverse.

    This is the regularized solve used by the EME interface construction. The
    smallest singular directions of ``A`` are the first place where truncated
    mode sets become numerically unstable, so the solve is performed as

    ``X = pinv_tsvd(A) @ B``

    with a relative cutoff

    ``s_cut = rcond * s_max``.

    Singular values below ``s_cut`` are discarded entirely.

    High-level behavior:
        - small ``rcond`` keeps more singular directions and is closer to the
          exact inverse, but is more sensitive to ill-conditioning;
        - large ``rcond`` drops more singular directions and is more stable,
          but biases the result towards a lower-rank approximation.

    This routine does not enforce passivity by itself. It only stabilizes the
    linear inversion. Passivity is handled afterwards on the assembled
    interface S-matrix.

    Args:
        A: System matrix to invert approximately.
        B: Right-hand side.
        rcond: Relative singular-value cutoff. Singular values smaller than
            ``rcond * max(s)`` are discarded.

    Returns:
        A tuple ``(X, s, s_cut, rank_kept)`` containing the solved result,
        the singular values of ``A``, the absolute cutoff, and the number of
        retained singular directions.

    Raises:
        RuntimeError: If all singular values are rejected.
    """
    U, s, Vh = np.linalg.svd(A, full_matrices=False)
    s_cut = rcond * float(s[0]) if s.size else 0.0
    keep = s >= s_cut
    if not np.any(keep):
        msg = "TSVD rejected all singular values; lower rcond."
        raise RuntimeError(msg)
    A_pinv = (Vh.conj().T[:, keep] * (1.0 / s[keep])) @ U.conj().T[keep, :]
    X = A_pinv @ B
    return X, s, s_cut, int(np.count_nonzero(keep))

visualize

visualize(obj: Any, **kwargs: Any) -> Any

Visualize any meow object.

Parameters:

Name Type Description Default
obj Any

the meow object to visualize

required
**kwargs Any

extra configuration to visualize the object

{}
Note

Most meow objects have a ._visualize method. Check out its help to see which kwargs are accepted.

Source code in src/meow/visualization.py
def visualize(obj: Any, **kwargs: Any) -> Any:
    """Visualize any meow object.

    Args:
        obj: the meow object to visualize
        **kwargs: extra configuration to visualize the object

    Note:
        Most meow objects have a `._visualize` method.
        Check out its help to see which kwargs are accepted.
    """
    try:
        is_empty = bool(not obj)
    except ValueError:
        is_empty = isinstance(obj, np.ndarray) and obj.size == 0

    if is_empty:
        msg = "Nothing to visualize!"
        raise ValueError(msg)

    vis_func = _get_vis_func(obj)
    vis_func(obj, **kwargs)

zero_phase

zero_phase(mode: Mode) -> Mode

Normalize (zero out) the phase of a Mode.

Source code in src/meow/mode.py
def zero_phase(mode: Mode) -> Mode:
    """Normalize (zero out) the phase of a `Mode`."""
    e = np.abs(energy_density(mode))
    m, n = np.array(np.where(e == e.max()))[:, 0]
    phase = np.exp(-1j * np.angle(np.array(mode.Hx))[m][n])
    new_mode = Mode(
        neff=mode.neff,
        cs=mode.cs,
        Ex=mode.Ex * phase,
        Ey=mode.Ey * phase,
        Ez=mode.Ez * phase,
        Hx=mode.Hx * phase,
        Hy=mode.Hy * phase,
        Hz=mode.Hz * phase,
    )
    if _sum_around(np.real(new_mode.Hx), int(m), int(n)) < 0:
        new_mode = invert_mode(new_mode)
    return new_mode