"""A physical layer stack with Sellmeier dispersion.

The `LayerStack` describes the physical reality of the process — what
sits on what, how thick each layer is, and the material's dispersive
refractive index. Simulators (mode solvers, FDTD wrappers) read the
stack to set up their cross-section.
"""
import lumicron as lm
import lumicron_pdk as lpdk

LAYER = lpdk.LayerTable(
    BOX  = lpdk.Layer(1, 0, color="#87ceeb"),
    SILC = lpdk.Layer(9, 0, color="#008000", min_width=0.2,
                    min_spacing=0.2, min_radius=5.0),
    SILN = lpdk.Layer(5, 0, color="#ff69b4", min_width=0.4,
                    min_spacing=0.3, min_radius=10.0),
    CLAD = lpdk.Layer(2, 0, color="#aac7e8"),
    MTL1 = lpdk.Layer(4, 0, color="#ffd700"),
)

# Sellmeier coefficients describe n(λ) for a material. The form is
# n²(λ) − 1 = Σ B_i · λ² / (λ² − C_i).
SiO2 = lpdk.Sellmeier(
    B=[0.6962, 0.4079, 0.8975],
    C=[0.0684**2, 0.1162**2, 9.8962**2],
)
Si = lpdk.Sellmeier(
    B=[10.6684, 0.0030, 1.5413],
    C=[0.3015**2, 1.1348**2, 1104.0**2],
)
SiN = lpdk.Sellmeier(B=[2.8939], C=[0.1397**2])

STACK = lpdk.LayerStack(
    lpdk.StackLayer("BOX",      layer=LAYER.BOX,  thickness=2.0,  sellmeier=SiO2),
    lpdk.StackLayer("core_si",  layer=LAYER.SILC, thickness=0.22, sellmeier=Si),
    lpdk.StackLayer("core_sin", layer=LAYER.SILN, thickness=0.4,  sellmeier=SiN),
    lpdk.StackLayer("clad",     layer=LAYER.CLAD, thickness=2.0,  sellmeier=SiO2),
    lpdk.StackLayer("metal1",   layer=LAYER.MTL1, thickness=1.0,  n=0.0),
)


@lm.pcell
def StackPreview():
    """A layout that exposes the stack's process layers as a strip."""
    c = lm.CELL("StackPreview")
    for i, name in enumerate(["BOX", "SILC", "SILN", "CLAD", "MTL1"]):
        rect = lm.Rectangle(x_dim=80, y_dim=20, layer=getattr(LAYER, name))
        h = c.add(rect)
        c.Place(h).at((0, i * 30))
    return c


if __name__ == "__main__":
    StackPreview().to_gds("stack_preview.gds")
