benvial/gyptis

View on GitHub
examples/diffraction/plot_pec_grating.py

Summary

Maintainability
A
0 mins
Test Coverage
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Benjamin Vial
# This file is part of gyptis
# Version: 1.0.2
# License: MIT
# See the documentation at gyptis.gitlab.io
"""
2D PEC Grating
==============

Example of a perfectly conducting diffraction grating.
"""


from collections import OrderedDict

import matplotlib.pyplot as plt
import numpy as np

import gyptis as gy

##############################################################################
# We will study a classical benchmark of a perfectly conducting
# grating and compare with results given in :cite:p:`PopovGratingBook`.
#

lambda0 = 600
theta0 = 20

period = 800
h = 8
w = 600

pmesh = 10

thicknesses = OrderedDict(
    {
        "pml_bottom": 1 * lambda0,
        "substrate": 1 * lambda0,
        "groove": 20 * h,
        "superstrate": 1 * lambda0,
        "pml_top": 1 * lambda0,
    }
)

mesh_param = dict(
    {
        "pml_bottom": 0.7 * pmesh,
        "substrate": pmesh,
        "groove": pmesh,
        "superstrate": pmesh,
        "pml_top": 0.7 * pmesh,
    }
)

######################################################################
# Let's create the geometry

geom = gy.Layered(2, period, thicknesses)
groove = geom.layers["groove"]
y0 = geom.y_position["groove"] + thicknesses["groove"] / 2
rod = geom.add_ellipse(0, y0, 0, w / 2, h / 2)
groove = geom.cut(groove, rod, removeTool=True)
geom.add_physical(groove, "groove")

mesh_size = {d: lambda0 / param for d, param in mesh_param.items()}


rod_bnds = geom.get_boundaries("groove")[-1]
geom.add_physical(rod_bnds, "rod_bnds", dim=1)
geom.set_mesh_size(mesh_size)
geom.set_mesh_size({"rod_bnds": h / 8}, dim=1)

geom.build(
    interactive=False,
    generate_mesh=True,
    write_mesh=True,
    read_info=True,
)


domains = [k for k in thicknesses.keys() if k not in ["pml_bottom", "pml_top"]]

epsilon = {d: 1 for d in domains}
mu = {d: 1 for d in domains}

angle = theta0 * np.pi / 180
pw = gy.PlaneWave(lambda0, angle, dim=2)

gratingTM = gy.Grating(
    geom,
    epsilon,
    mu,
    source=pw,
    polarization="TM",
    degree=2,
    boundary_conditions={"rod_bnds": "PEC"},
)


gratingTM.solve()
effs_TM = gratingTM.diffraction_efficiencies(1, orders=True)

E = gratingTM.solution["total"]

# reference
T_ref = dict(TM=[0.0639, 1.0000], TE=[0.1119, 1.0000])

print("Transmission coefficient (TM)")
print(" order      ref       calc")
print("--------------------------------")
print(f"   0       {T_ref['TM'][0]:.4f}    {effs_TM['T'][1]:.4f} ")
print(f"  sum      {T_ref['TM'][1]:.4f}    {effs_TM['B']:.4f}   ")


######################################################################
# We switch to TE polarization

gratingTE = gy.Grating(
    geom,
    epsilon,
    mu,
    source=pw,
    polarization="TE",
    degree=2,
    boundary_conditions={"rod_bnds": "PEC"},
)

gratingTE.solve()
effs_TE = gratingTE.diffraction_efficiencies(2, orders=True)

H = gratingTE.solution["total"]


fig, ax = plt.subplots(1, 2)
ylim = geom.y_position["substrate"], geom.y_position["pml_top"]
gratingTM.plot_field(ax=ax[0])
gratingTM.plot_geometry(ax=ax[0])
ax[0].set_ylim(ylim)
ax[0].set_axis_off()
ax[0].set_title("$E_z$ (TM)")
gratingTE.plot_field(ax=ax[1])
gratingTE.plot_geometry(ax=ax[1])
ax[1].set_ylim(ylim)
ax[1].set_axis_off()
ax[1].set_title("$H_z$ (TE)")
fig.tight_layout()
fig.show()

print("Transmission coefficient (TE)")
print(" order      ref       calc")
print("--------------------------------")
print(f"   0       {T_ref['TE'][0]:.4f}    {effs_TE['T'][1]:.4f} ")
print(f"  sum      {T_ref['TE'][1]:.4f}    {effs_TE['B']:.4f}   ")