Beispiel #1
0
def plt_mode_fields(sim_wguide,
                    ivals=None,
                    n_points=500,
                    quiver_steps=50,
                    xlim_min=None,
                    xlim_max=None,
                    ylim_min=None,
                    ylim_max=None,
                    EM_AC='EM_E',
                    num_ticks=None,
                    contours=False,
                    contour_lst=None,
                    stress_fields=False,
                    pdf_png='png',
                    prefix_str='',
                    suffix_str=''):
    """ Plot E or H fields of EM mode, or the AC modes displacement fields.

        Args:
            sim_wguide : A ``Struct`` instance that has had calc_modes calculated

        Keyword Args:
            ivals  (list): mode numbers of modes you wish to plot

            n_points  (int): The number of points across unitcell to
                interpolate the field onto

            xlim_min  (float): Limit plotted xrange to xlim_min:(1-xlim_max) of unitcell

            xlim_max  (float): Limit plotted xrange to xlim_min:(1-xlim_max) of unitcell

            ylim_min  (float): Limit plotted yrange to ylim_min:(1-ylim_max) of unitcell

            ylim_max  (float): Limit plotted yrange to ylim_min:(1-ylim_max) of unitcell

            EM_AC  (str): Either 'EM' or 'AC' modes

            num_ticks  (int): Number of tick marks

            contours  (bool): Controls contours being overlaid on fields

            contour_lst  (list): Specify contour values

            stress_fields  (bool): Calculate acoustic stress fields

            pdf_png  (str): File type to save, either 'png' or 'pdf' 

            prefix_str  (str): Add a string to start of file name
            
            suffix_str  (str): Add a string to end of file name.
    """

    if EM_AC is not 'EM_E' and EM_AC is not 'EM_H' and EM_AC is not 'AC':
        raise ValueError("EM_AC must be either 'AC', 'EM_E' or 'EM_H'.")

    # Calculate the magnetic field from the electric field
    if EM_AC == 'EM_H':
        nnodes = 6
        sim_wguide.sol1_H = NumBAT.h_mode_field_ez(
            sim_wguide.k_0, sim_wguide.num_modes, sim_wguide.n_msh_el,
            sim_wguide.n_msh_pts, nnodes, sim_wguide.table_nod,
            sim_wguide.x_arr, sim_wguide.Eig_values, sim_wguide.sol1)

    plt.clf()

    # field mapping
    x_tmp = []
    y_tmp = []
    for i in np.arange(sim_wguide.n_msh_pts):
        x_tmp.append(sim_wguide.x_arr[0, i])
        y_tmp.append(sim_wguide.x_arr[1, i])
    x_min = np.min(x_tmp)
    x_max = np.max(x_tmp)
    y_min = np.min(y_tmp)
    y_max = np.max(y_tmp)
    area = abs((x_max - x_min) * (y_max - y_min))
    n_pts_x = int(n_points * abs(x_max - x_min) / np.sqrt(area))
    n_pts_y = int(n_points * abs(y_max - y_min) / np.sqrt(area))
    v_x = np.zeros(n_pts_x * n_pts_y)
    v_y = np.zeros(n_pts_x * n_pts_y)
    if contours:
        v_XX, v_YY = np.meshgrid(range(n_pts_x), range(n_pts_y))
    i = 0
    for x in np.linspace(x_min, x_max, n_pts_x):
        for y in np.linspace(y_min, y_max, n_pts_y):
            v_x[i] = x
            v_y[i] = y
            i += 1
    v_x = np.array(v_x)
    v_y = np.array(v_y)

    # unrolling data for the interpolators
    table_nod = sim_wguide.table_nod.T
    x_arr = sim_wguide.x_arr.T

    if ivals:
        ival_range = ivals
    else:
        ival_range = range(len(sim_wguide.Eig_values))

    for ival in ival_range:
        # dense triangulation with multiple points
        v_x6p = np.zeros(6 * sim_wguide.n_msh_el)
        v_y6p = np.zeros(6 * sim_wguide.n_msh_el)
        v_Ex6p = np.zeros(6 * sim_wguide.n_msh_el, dtype=np.complex128)
        v_Ey6p = np.zeros(6 * sim_wguide.n_msh_el, dtype=np.complex128)
        v_Ez6p = np.zeros(6 * sim_wguide.n_msh_el, dtype=np.complex128)
        v_triang6p = []

        i = 0
        for i_el in np.arange(sim_wguide.n_msh_el):
            # triangles
            idx = np.arange(6 * i_el, 6 * (i_el + 1))
            triangles = [[idx[0], idx[3], idx[5]], [idx[1], idx[4], idx[3]],
                         [idx[2], idx[5], idx[4]], [idx[3], idx[4], idx[5]]]
            v_triang6p.extend(triangles)

            for i_node in np.arange(6):
                # index for the coordinates
                i_ex = table_nod[i_el, i_node] - 1
                # values
                v_x6p[i] = x_arr[i_ex, 0]
                v_y6p[i] = x_arr[i_ex, 1]

                if EM_AC == 'EM_E' or EM_AC == 'AC':
                    v_Ex6p[i] = sim_wguide.sol1[0, i_node, ival, i_el]
                    v_Ey6p[i] = sim_wguide.sol1[1, i_node, ival, i_el]
                    v_Ez6p[i] = sim_wguide.sol1[2, i_node, ival, i_el]
                if EM_AC == 'EM_H':
                    v_Ex6p[i] = sim_wguide.sol1_H[0, i_node, ival, i_el]
                    v_Ey6p[i] = sim_wguide.sol1_H[1, i_node, ival, i_el]
                    v_Ez6p[i] = sim_wguide.sol1_H[2, i_node, ival, i_el]
                i += 1

        v_E6p = np.sqrt(
            np.abs(v_Ex6p)**2 + np.abs(v_Ey6p)**2 + np.abs(v_Ez6p)**2)

        ### Interpolate onto triangular grid - honest to FEM elements
        # dense triangulation with unique points
        v_triang1p = []
        for i_el in np.arange(sim_wguide.n_msh_el):
            # triangles
            triangles = [[
                table_nod[i_el, 0] - 1, table_nod[i_el, 3] - 1,
                table_nod[i_el, 5] - 1
            ],
                         [
                             table_nod[i_el, 1] - 1, table_nod[i_el, 4] - 1,
                             table_nod[i_el, 3] - 1
                         ],
                         [
                             table_nod[i_el, 2] - 1, table_nod[i_el, 5] - 1,
                             table_nod[i_el, 4] - 1
                         ],
                         [
                             table_nod[i_el, 3] - 1, table_nod[i_el, 4] - 1,
                             table_nod[i_el, 5] - 1
                         ]]
            v_triang1p.extend(triangles)

        # triangulations
        triang6p = matplotlib.tri.Triangulation(v_x6p, v_y6p, v_triang6p)
        triang1p = matplotlib.tri.Triangulation(x_arr[:, 0], x_arr[:, 1],
                                                v_triang1p)

        # building interpolators: triang1p for the finder, triang6p for the values
        finder = matplotlib.tri.TrapezoidMapTriFinder(triang1p)
        ReEx = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ex6p.real,
                                                    trifinder=finder)
        ImEx = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ex6p.imag,
                                                    trifinder=finder)
        ReEy = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ey6p.real,
                                                    trifinder=finder)
        ImEy = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ey6p.imag,
                                                    trifinder=finder)
        ReEz = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ez6p.real,
                                                    trifinder=finder)
        ImEz = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ez6p.imag,
                                                    trifinder=finder)
        AbsE = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_E6p,
                                                    trifinder=finder)
        # interpolated fields
        m_ReEx = ReEx(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ReEy = ReEy(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ReEz = ReEz(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ImEx = ImEx(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ImEy = ImEy(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ImEz = ImEz(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_AbsE = AbsE(v_x, v_y).reshape(n_pts_x, n_pts_y)

        # Flip y order as imshow has origin at top left
        v_plots = [
            m_ReEx[:, ::-1], m_ReEy[:, ::-1], m_ReEz[:, ::-1], m_ImEx[:, ::-1],
            m_ImEy[:, ::-1], m_ImEz[:, ::-1], m_AbsE[:, ::-1]
        ]
        if EM_AC == 'EM_E':
            v_labels = [
                r"Re($E_x$)", r"Re($E_y$)", r"Re($E_z$)", r"Im($E_x$)",
                r"Im($E_y$)", r"Im($E_z$)", r"$|E|$"
            ]
        elif EM_AC == 'EM_H':
            v_labels = [
                r"Re($H_x$)", r"Re($H_y$)", r"Re($H_z$)", r"Im($H_x$)",
                r"Im($H_y$)", r"Im($H_z$)", r"$|H|$"
            ]
        else:
            v_labels = [
                r"Re($u_x$)", r"Re($u_y$)", r"Re($u_z$)", r"Im($u_x$)",
                r"Im($u_y$)", r"Im($u_z$)", r"$|u|$"
            ]

        # field plots
        plot_threshold = 1e-4  # set negligible components to explicitly zero
        plt.clf()
        fig = plt.figure(figsize=(15, 15))
        for i_p, plot in enumerate(v_plots):
            ax = plt.subplot(3, 3, i_p + 1)
            if np.max(np.abs(plot[~np.isnan(plot)])) < plot_threshold:
                # im = plt.imshow(plot.T,cmap='viridis');
                im = plt.imshow(np.zeros(np.shape(plot.T)))
            else:
                im = plt.imshow(plot.T)
            # ax.set_aspect('equal')
            # no ticks
            plt.xticks([])
            plt.yticks([])
            # limits
            axes = plt.gca()
            xmin, xmax = axes.get_xlim()
            ymin, ymax = axes.get_ylim()
            width_x = xmax - xmin
            width_y = ymax - ymin
            if xlim_min != None:
                ax.set_xlim(xmin + xlim_min * width_x,
                            xmax - xlim_max * width_x)
            if ylim_min != None:
                ax.set_ylim(ymin + ylim_min * width_y,
                            ymax - ylim_max * width_y)
            # titles
            plt.title(v_labels[i_p], fontsize=title_font - 4)
            # colorbar
            divider = make_axes_locatable(ax)
            cax = divider.append_axes("right", size="5%", pad=0.1)
            cbar = plt.colorbar(im, cax=cax)
            if num_ticks:
                cbarticks = np.linspace(np.min(plot),
                                        np.max(plot),
                                        num=num_ticks)
            elif ylim_min != None:
                if xlim_min / ylim_min > 3:
                    cbarticks = np.linspace(np.min(plot), np.max(plot), num=3)
                if xlim_min / ylim_min > 1.5:
                    cbarticks = np.linspace(np.min(plot), np.max(plot), num=5)
                else:
                    cbarticks = np.linspace(np.min(plot), np.max(plot), num=7)
            else:
                cbarticks = np.linspace(np.min(plot), np.max(plot), num=7)
            cbar.set_ticks(cbarticks)
            cbarlabels = ['%.2f' % t for t in cbarticks]
            cbar.set_ticklabels(cbarlabels)
            if contours:
                if contour_lst:
                    cbarticks = contour_lst
                if np.max(np.abs(plot[~np.isnan(plot)])) > plot_threshold:
                    CS2 = ax.contour(v_XX,
                                     v_YY,
                                     plot.T,
                                     levels=cbarticks,
                                     colors=colors[::-1],
                                     linewidths=(1.5, ))
                    cbar.add_lines(CS2)
            cbar.ax.tick_params(labelsize=title_font - 10)

        if EM_AC == 'AC':
            v_x_q = v_x.reshape(n_pts_x, n_pts_y)
            v_y_q = v_y.reshape(n_pts_x, n_pts_y)
            v_x_q = v_x_q[0::quiver_steps, 0::quiver_steps]
            v_y_q = v_y_q[0::quiver_steps, 0::quiver_steps]
            m_ReEx_q = m_ReEx[0::quiver_steps, 0::quiver_steps]
            m_ReEy_q = m_ReEy[0::quiver_steps, 0::quiver_steps]
            m_ImEx_q = m_ImEx[0::quiver_steps, 0::quiver_steps]
            m_ImEy_q = m_ImEy[0::quiver_steps, 0::quiver_steps]
            ax = plt.subplot(3, 3, i_p + 2)
            plt.quiver(
                v_x_q,
                v_y_q,
                (m_ReEx_q + m_ImEx_q),
                (m_ReEy_q + m_ImEy_q),  # data
                np.sqrt(
                    np.real((m_ReEx_q + 1j * m_ImEx_q) *
                            (m_ReEx_q - 1j * m_ImEx_q) +
                            (m_ReEy_q + 1j * m_ImEy_q) *
                            (m_ReEy_q - 1j * m_ImEy_q))
                ),  #colour the arrows based on this array
                linewidths=(0.2, ),
                edgecolors=('k'),
                pivot='mid',
                headlength=5)  # length of the arrows
            ax.set_aspect('equal')
            plt.xticks([])
            plt.yticks([])
            axes = plt.gca()
            xmin, xmax = axes.get_xlim()
            ymin, ymax = axes.get_ylim()
            if xlim_min != None:
                ax.set_xlim(xlim_min * xmax, (1 - xlim_max) * xmax)
            if ylim_min != None:
                ax.set_ylim((1 - ylim_min) * ymin, ylim_max * ymin)
            plt.title('Transverse', fontsize=title_font - 4)

        if EM_AC == 'EM_E' or EM_AC == 'EM_H':
            n_eff = sim_wguide.Eig_values[ival] * sim_wguide.wl_m / (2 * np.pi)
            if np.imag(sim_wguide.Eig_values[ival]) < 0:
                k_str = r'$k_z = %(re_k)f %(im_k)f i$'% \
                    {'re_k' : np.real(sim_wguide.Eig_values[ival]),
                    'im_k' : np.imag(sim_wguide.Eig_values[ival])}
                n_str = r'$n_{eff} = %(re_k)f %(im_k)f i$'% \
                    {'re_k' : np.real(n_eff), 'im_k' : np.imag(n_eff)}
            else:
                k_str = r'$k_z = %(re_k)f + %(im_k)f i$'% \
                    {'re_k' : np.real(sim_wguide.Eig_values[ival]),
                    'im_k' : np.imag(sim_wguide.Eig_values[ival])}
                n_str = r'$n_{eff} = %(re_k)f + %(im_k)f i$'% \
                    {'re_k' : np.real(n_eff), 'im_k' : np.imag(n_eff)}
            # plt.text(10, 0.3, n_str, fontsize=title_font)
        else:
            n_str = ''
            if np.imag(sim_wguide.Eig_values[ival]) < 0:
                k_str = r'$\Omega/2\pi = %(re_k)f %(im_k)f i$ GHz'% \
                    {'re_k' : np.real(sim_wguide.Eig_values[ival]*1e-9),
                    'im_k' : np.imag(sim_wguide.Eig_values[ival]*1e-9)}
            else:
                k_str = r'$\Omega/2\pi = %(re_k)f + %(im_k)f i$ GHz'% \
                    {'re_k' : np.real(sim_wguide.Eig_values[ival]*1e-9),
                    'im_k' : np.imag(sim_wguide.Eig_values[ival]*1e-9)}
        # plt.text(10, 0.5, k_str, fontsize=title_font)
        plt.suptitle('Mode #' + str(ival) + '   ' + k_str + '   ' + n_str +
                     "\n",
                     fontsize=title_font)
        # plt.tight_layout(pad=2.5, w_pad=0.5, h_pad=1.0)
        fig.set_tight_layout(True)

        if not os.path.exists("%sfields" % prefix_str):
            os.mkdir("%sfields" % prefix_str)
        if pdf_png == 'png':
            plt.savefig('%(pre)sfields/%(s)s_field_%(i)i%(add)s.png' % {
                'pre': prefix_str,
                's': EM_AC,
                'i': ival,
                'add': suffix_str
            })
            #, bbox_inches='tight') - this caused error in Q calc... ?
        elif pdf_png == 'pdf':
            plt.savefig('%(pre)sfields/%(s)s_field_%(i)i%(add)s.pdf' % {
                'pre': prefix_str,
                's': EM_AC,
                'i': ival,
                'add': suffix_str
            },
                        bbox_inches='tight')
        else:
            raise ValueError("pdf_png must be either 'png' or 'pdf'.")
        plt.close()

        if EM_AC == 'AC' and stress_fields is True:
            ### Interpolate onto rectangular Cartesian grid
            xy = list(zip(v_x6p, v_y6p))
            grid_x, grid_y = np.mgrid[x_min:x_max:n_pts_x * 1j,
                                      y_min:y_max:n_pts_y * 1j]
            m_ReEx = interpolate.griddata(xy,
                                          v_Ex6p.real, (grid_x, grid_y),
                                          method='linear')
            m_ReEy = interpolate.griddata(xy,
                                          v_Ey6p.real, (grid_x, grid_y),
                                          method='linear')
            m_ReEz = interpolate.griddata(xy,
                                          v_Ez6p.real, (grid_x, grid_y),
                                          method='linear')
            m_ImEx = interpolate.griddata(xy,
                                          v_Ex6p.imag, (grid_x, grid_y),
                                          method='linear')
            m_ImEy = interpolate.griddata(xy,
                                          v_Ey6p.imag, (grid_x, grid_y),
                                          method='linear')
            m_ImEz = interpolate.griddata(xy,
                                          v_Ez6p.imag, (grid_x, grid_y),
                                          method='linear')
            m_AbsE = interpolate.griddata(xy,
                                          v_E6p.real, (grid_x, grid_y),
                                          method='linear')
            dx = grid_x[-1, 0] - grid_x[-2, 0]
            dy = grid_y[0, -1] - grid_y[0, -2]
            m_Ex = m_ReEx + 1j * m_ImEx
            m_Ey = m_ReEy + 1j * m_ImEy
            m_Ez = m_ReEz + 1j * m_ImEz
            m_Ex = m_Ex.reshape(n_pts_x, n_pts_y)
            m_Ey = m_Ey.reshape(n_pts_x, n_pts_y)
            m_Ez = m_Ez.reshape(n_pts_x, n_pts_y)
            m_AbsE = m_AbsE.reshape(n_pts_x, n_pts_y)

            m_ReEx = np.real(m_Ex)
            m_ReEy = np.real(m_Ey)
            m_ReEz = np.real(m_Ez)
            m_ImEx = np.imag(m_Ex)
            m_ImEy = np.imag(m_Ey)
            m_ImEz = np.imag(m_Ez)

            del_x_Ex = np.gradient(m_Ex, dx, axis=0)
            del_y_Ex = np.gradient(m_Ex, dy, axis=1)
            del_x_Ey = np.gradient(m_Ey, dx, axis=0)
            del_y_Ey = np.gradient(m_Ey, dy, axis=1)
            del_x_Ez = np.gradient(m_Ez, dx, axis=0)
            del_y_Ez = np.gradient(m_Ez, dy, axis=1)
            del_z_Ex = 1j * sim_wguide.k_AC * m_Ex
            del_z_Ey = 1j * sim_wguide.k_AC * m_Ey
            del_z_Ez = 1j * sim_wguide.k_AC * m_Ez

            # Flip y order as imshow has origin at top left
            del_mat = np.array([
                del_x_Ex[:, ::-1].real, del_x_Ey[:, ::-1].real,
                del_x_Ez[:, ::-1].real, del_x_Ex[:, ::-1].imag,
                del_x_Ey[:, ::-1].imag, del_x_Ez[:, ::-1].imag,
                del_y_Ex[:, ::-1].real, del_y_Ey[:, ::-1].real,
                del_y_Ez[:, ::-1].real, del_y_Ex[:, ::-1].imag,
                del_y_Ey[:, ::-1].imag, del_y_Ez[:, ::-1].imag,
                del_z_Ex[:, ::-1].real, del_z_Ey[:, ::-1].real,
                del_z_Ez[:, ::-1].real, del_z_Ex[:, ::-1].imag,
                del_z_Ey[:, ::-1].imag, del_z_Ez[:, ::-1].imag
            ])
            v_labels = [
                "Re($S_{xx}$)", "Re($S_{xy}$)", "Re($S_{xz}$)", "Im($S_{xx}$)",
                "Im($S_{xy}$)", "Im($S_{xz}$)", "Re($S_{yx}$)", "Re($S_{yy}$)",
                "Re($S_{yz}$)", "Im($S_{yx}$)", "Im($S_{yy}$)", "Im($S_{yz}$)",
                "Re($S_{zx}$)", "Re($S_{zy}$)", "Re($S_{zz}$)", "Im($S_{zx}$)",
                "Im($S_{zy}$)", "Im($S_{zz}$)"
            ]

            # field plots
            plt.clf()
            fig = plt.figure(figsize=(15, 30))
            for i_p, plot in enumerate(del_mat):
                ax = plt.subplot(6, 3, i_p + 1)
                im = plt.imshow(plot.T)
                # no ticks
                plt.xticks([])
                plt.yticks([])
                # limits
                if xlim_min != None:
                    ax.set_xlim(xlim_min * n_points, (1 - xlim_max) * n_points)
                if ylim_min != None:
                    ax.set_ylim((1 - ylim_min) * n_points, ylim_max * n_points)
                # titles
                plt.title(v_labels[i_p], fontsize=title_font - 4)
                # colorbar
                divider = make_axes_locatable(ax)
                cax = divider.append_axes("right", size="5%", pad=0.1)
                cbar = plt.colorbar(im, cax=cax, format='%.2e')
                if num_ticks:
                    cbarticks = np.linspace(np.min(plot),
                                            np.max(plot),
                                            num=num_ticks)
                elif ylim_min != None:
                    if xlim_min / ylim_min > 3:
                        cbarlabels = np.linspace(np.min(plot),
                                                 np.max(plot),
                                                 num=3)
                    if xlim_min / ylim_min > 1.5:
                        cbarlabels = np.linspace(np.min(plot),
                                                 np.max(plot),
                                                 num=5)
                    else:
                        cbarlabels = np.linspace(np.min(plot),
                                                 np.max(plot),
                                                 num=7)
                else:
                    cbarlabels = np.linspace(np.min(plot), np.max(plot), num=7)
                cbar.set_ticks(cbarlabels)
                cbarlabels = ['%.2f' % t for t in cbarlabels]
                cbar.set_ticklabels(cbarlabels)
                if contours:
                    if contour_lst:
                        cbarticks = contour_lst
                        print(contour_lst)
                    if np.max(np.abs(plot[~np.isnan(plot)])) > plot_threshold:
                        CS2 = ax.contour(v_XX,
                                         v_YY,
                                         plot.T,
                                         levels=cbarticks,
                                         colors=colors[::-1],
                                         linewidths=(1.5, ))
                    cbar.add_lines(CS2)
                cbar.ax.tick_params(labelsize=title_font - 10)
            fig.set_tight_layout(True)
            n_str = ''
            if np.imag(sim_wguide.Eig_values[ival]) < 0:
                k_str = r'$\Omega/2\pi = %(re_k)f %(im_k)f i$ GHz'% \
                    {'re_k' : np.real(sim_wguide.Eig_values[ival]*1e-9),
                    'im_k' : np.imag(sim_wguide.Eig_values[ival]*1e-9)}
            else:
                k_str = r'$\Omega/2\pi = %(re_k)f + %(im_k)f i$ GHz'% \
                    {'re_k' : np.real(sim_wguide.Eig_values[ival]*1e-9),
                    'im_k' : np.imag(sim_wguide.Eig_values[ival]*1e-9)}
            plt.suptitle('Mode #' + str(ival) + '   ' + k_str + '   ' + n_str,
                         fontsize=title_font)

            if pdf_png == 'png':
                plt.savefig('%(pre)sfields/%(s)s_S_field_%(i)i%(add)s.png' % {
                    'pre': prefix_str,
                    's': EM_AC,
                    'i': ival,
                    'add': suffix_str
                })
            elif pdf_png == 'pdf':
                plt.savefig('%(pre)sfields/%(s)s_S_field_%(i)i%(add)s.pdf' % {
                    'pre': prefix_str,
                    's': EM_AC,
                    'i': ival,
                    'add': suffix_str
                },
                            bbox_inches='tight')
            plt.close()
Beispiel #2
0
def plt_mode_fields(sim_wguide,
                    ivals=None,
                    n_points=501,
                    quiver_steps=50,
                    xlim_min=None,
                    xlim_max=None,
                    ylim_min=None,
                    ylim_max=None,
                    EM_AC='EM_E',
                    num_ticks=None,
                    colorbar=True,
                    contours=False,
                    contour_lst=None,
                    stress_fields=False,
                    pdf_png='png',
                    prefix_str='',
                    suffix_str='',
                    ticks=False,
                    comps=None,
                    decorator=None):
    """ Plot E or H fields of EM mode, or the AC modes displacement fields.

        Args:
            sim_wguide : A ``Struct`` instance that has had calc_modes calculated

        Keyword Args:
            ivals  (list): mode numbers of modes you wish to plot

            n_points  (int): The number of points across unitcell to
                interpolate the field onto

            xlim_min  (float): Limit plotted xrange to xlim_min:(1-xlim_max) of unitcell

            xlim_max  (float): Limit plotted xrange to xlim_min:(1-xlim_max) of unitcell

            ylim_min  (float): Limit plotted yrange to ylim_min:(1-ylim_max) of unitcell

            ylim_max  (float): Limit plotted yrange to ylim_min:(1-ylim_max) of unitcell

            EM_AC  (str): Either 'EM' or 'AC' modes

            num_ticks  (int): Number of tick marks

            contours  (bool): Controls contours being overlaid on fields

            contour_lst  (list): Specify contour values

            stress_fields  (bool): Calculate acoustic stress fields

            pdf_png  (str): File type to save, either 'png' or 'pdf' 

            prefix_str  (str): Add a string to start of file name
            
            suffix_str  (str): Add a string to end of file name.
    """

    if EM_AC is not 'EM_E' and EM_AC is not 'EM_H' and EM_AC is not 'AC':
        raise ValueError("EM_AC must be either 'AC', 'EM_E' or 'EM_H'.")

    # Calculate the magnetic field from the electric field
    if EM_AC == 'EM_H':
        nnodes = 6
        sim_wguide.sol1_H = NumBAT.h_mode_field_ez(
            sim_wguide.k_0, sim_wguide.num_modes, sim_wguide.n_msh_el,
            sim_wguide.n_msh_pts, nnodes, sim_wguide.table_nod,
            sim_wguide.x_arr, sim_wguide.Eig_values, sim_wguide.sol1)

    plt.clf()

    # field mapping
    x_tmp = []
    y_tmp = []
    for i in np.arange(sim_wguide.n_msh_pts):
        x_tmp.append(sim_wguide.x_arr[0, i])
        y_tmp.append(sim_wguide.x_arr[1, i])
    x_min = np.min(x_tmp)
    x_max = np.max(x_tmp)
    y_min = np.min(y_tmp)
    y_max = np.max(y_tmp)
    area = abs((x_max - x_min) * (y_max - y_min))
    n_pts_x = int(n_points * abs(x_max - x_min) / np.sqrt(area))
    n_pts_y = int(n_points * abs(y_max - y_min) / np.sqrt(area))
    v_x = np.zeros(n_pts_x * n_pts_y)
    v_y = np.zeros(n_pts_x * n_pts_y)
    v_XX = None
    v_YY = None
    if contours:
        v_XX, v_YY = np.meshgrid(range(n_pts_x), range(n_pts_y))
    i = 0
    for x in np.linspace(x_min, x_max, n_pts_x):
        for y in np.linspace(y_min, y_max, n_pts_y):
            v_x[i] = x
            v_y[i] = y
            i += 1
    v_x = np.array(v_x)
    v_y = np.array(v_y)

    # unrolling data for the interpolators
    table_nod = sim_wguide.table_nod.T
    x_arr = sim_wguide.x_arr.T

    if ivals:
        ival_range = ivals
    else:
        ival_range = range(len(sim_wguide.Eig_values))

    for ival in ival_range:
        # dense triangulation with multiple points
        v_x6p = np.zeros(6 * sim_wguide.n_msh_el)
        v_y6p = np.zeros(6 * sim_wguide.n_msh_el)
        v_Ex6p = np.zeros(6 * sim_wguide.n_msh_el, dtype=np.complex128)
        v_Ey6p = np.zeros(6 * sim_wguide.n_msh_el, dtype=np.complex128)
        v_Ez6p = np.zeros(6 * sim_wguide.n_msh_el, dtype=np.complex128)
        v_triang6p = []

        i = 0
        for i_el in np.arange(sim_wguide.n_msh_el):
            # triangles
            idx = np.arange(6 * i_el, 6 * (i_el + 1))
            triangles = [[idx[0], idx[3], idx[5]], [idx[1], idx[4], idx[3]],
                         [idx[2], idx[5], idx[4]], [idx[3], idx[4], idx[5]]]
            v_triang6p.extend(triangles)

            for i_node in np.arange(6):
                # index for the coordinates
                i_ex = table_nod[i_el, i_node] - 1
                # values
                v_x6p[i] = x_arr[i_ex, 0]
                v_y6p[i] = x_arr[i_ex, 1]

                if EM_AC == 'EM_E' or EM_AC == 'AC':
                    v_Ex6p[i] = sim_wguide.sol1[0, i_node, ival, i_el]
                    v_Ey6p[i] = sim_wguide.sol1[1, i_node, ival, i_el]
                    v_Ez6p[i] = sim_wguide.sol1[2, i_node, ival, i_el]
                if EM_AC == 'EM_H':
                    v_Ex6p[i] = sim_wguide.sol1_H[0, i_node, ival, i_el]
                    v_Ey6p[i] = sim_wguide.sol1_H[1, i_node, ival, i_el]
                    v_Ez6p[i] = sim_wguide.sol1_H[2, i_node, ival, i_el]
                i += 1

        v_E6p = np.sqrt(
            np.abs(v_Ex6p)**2 + np.abs(v_Ey6p)**2 + np.abs(v_Ez6p)**2)

        ### Interpolate onto triangular grid - honest to FEM elements
        # dense triangulation with unique points
        v_triang1p = []
        for i_el in np.arange(sim_wguide.n_msh_el):
            # triangles
            triangles = [[
                table_nod[i_el, 0] - 1, table_nod[i_el, 3] - 1,
                table_nod[i_el, 5] - 1
            ],
                         [
                             table_nod[i_el, 1] - 1, table_nod[i_el, 4] - 1,
                             table_nod[i_el, 3] - 1
                         ],
                         [
                             table_nod[i_el, 2] - 1, table_nod[i_el, 5] - 1,
                             table_nod[i_el, 4] - 1
                         ],
                         [
                             table_nod[i_el, 3] - 1, table_nod[i_el, 4] - 1,
                             table_nod[i_el, 5] - 1
                         ]]
            v_triang1p.extend(triangles)

        # triangulations
        triang6p = matplotlib.tri.Triangulation(v_x6p, v_y6p, v_triang6p)
        triang1p = matplotlib.tri.Triangulation(x_arr[:, 0], x_arr[:, 1],
                                                v_triang1p)

        #fields are called Ex, Ey, etc regardless of whether we are plotting E, H, or u/S

        # building interpolators: triang1p for the finder, triang6p for the values
        #TODO: could be more efficient only interpolating the fields which are ultimately to be used?
        finder = matplotlib.tri.TrapezoidMapTriFinder(triang1p)
        ReEx = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ex6p.real,
                                                    trifinder=finder)
        ImEx = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ex6p.imag,
                                                    trifinder=finder)
        ReEy = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ey6p.real,
                                                    trifinder=finder)
        ImEy = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ey6p.imag,
                                                    trifinder=finder)
        ReEz = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ez6p.real,
                                                    trifinder=finder)
        ImEz = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_Ez6p.imag,
                                                    trifinder=finder)
        AbsE = matplotlib.tri.LinearTriInterpolator(triang6p,
                                                    v_E6p,
                                                    trifinder=finder)
        # interpolated fields
        m_ReEx = ReEx(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ReEy = ReEy(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ReEz = ReEz(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ImEx = ImEx(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ImEy = ImEy(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_ImEz = ImEz(v_x, v_y).reshape(n_pts_x, n_pts_y)
        m_AbsE = AbsE(v_x, v_y).reshape(n_pts_x, n_pts_y)

        v_x_q = v_x.reshape(n_pts_x, n_pts_y)
        v_y_q = v_y.reshape(n_pts_x, n_pts_y)
        v_x_q = v_x_q[0::quiver_steps, 0::quiver_steps]
        v_y_q = v_y_q[0::quiver_steps, 0::quiver_steps]
        m_ReEx_q = m_ReEx[0::quiver_steps, 0::quiver_steps]
        m_ReEy_q = m_ReEy[0::quiver_steps, 0::quiver_steps]
        m_ImEx_q = m_ImEx[0::quiver_steps, 0::quiver_steps]
        m_ImEy_q = m_ImEy[0::quiver_steps, 0::quiver_steps]

        ### No longer needed as imshow is using origin=lower
        # Flip y order as imshow has origin at top left
        #v_plots = [m_ReEx[:,::-1],m_ReEy[:,::-1],m_ReEz[:,::-1],m_ImEx[:,::-1],m_ImEy[:,::-1],m_ImEz[:,::-1],m_AbsE[:,::-1]]

        v_plots = [m_ReEx, m_ReEy, m_ReEz, m_ImEx, m_ImEy, m_ImEz, m_AbsE]
        vq_plots = [m_ReEx_q, m_ReEy_q, m_ImEx_q, m_ImEy_q]

        if EM_AC == 'EM_E':
            v_labels = [
                r"Re($E_x$)", r"Re($E_y$)", r"Re($E_z$)", r"Im($E_x$)",
                r"Im($E_y$)", r"Im($E_z$)", r"$|E|$"
            ]
        elif EM_AC == 'EM_H':
            v_labels = [
                r"Re($H_x$)", r"Re($H_y$)", r"Re($H_z$)", r"Im($H_x$)",
                r"Im($H_y$)", r"Im($H_z$)", r"$|H|$"
            ]
        else:
            v_labels = [
                r"Re($u_x$)", r"Re($u_y$)", r"Re($u_z$)", r"Im($u_x$)",
                r"Im($u_y$)", r"Im($u_z$)", r"$|u|$"
            ]

        if decorator == None: decorator = FieldDecorator()

        plot_params = {
            'xlim_min': xlim_min,
            'xlim_max': xlim_max,
            'ylim_min': ylim_min,
            'ylim_max': ylim_max,
            'ticks': ticks,
            'num_ticks': num_ticks,
            'colorbar': colorbar,
            'contours': contours,
            'contour_lst': contour_lst,
            'EM_AC': EM_AC,
            'prefix_str': prefix_str,
            'suffix_str': suffix_str,
            'pdf_png': pdf_png,
            'stress_fields': stress_fields,
            'decorator': decorator
        }

        if not os.path.exists("%sfields" % prefix_str):
            os.mkdir("%sfields" % prefix_str)

        decorator._set_for_multi()
        plot_all_components(v_x, v_y, v_x_q, v_y_q, v_XX, v_YY, v_plots,
                            vq_plots, v_labels, plot_params, sim_wguide, ival)

        decorator._set_for_single()
        if comps != None:
            for comp in comps:
                if comp == 'Ex' and EM_AC == 'EM_E':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[0],
                                   v_labels[0], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'Ey' and EM_AC == 'EM_E':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[1],
                                   v_labels[1], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'Ez' and EM_AC == 'EM_E':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[5],
                                   v_labels[5], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'Eabs' and EM_AC == 'EM_E':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[6],
                                   v_labels[6], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'Et' and EM_AC == 'EM_E':
                    plot_component(v_x_q, v_y_q, v_XX, v_YY, vq_plots,
                                   '$(E_x,E_y)$', plot_params, sim_wguide,
                                   ival, comp)
                elif comp == 'Hx' and EM_AC == 'EM_H':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[0],
                                   v_labels[0], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'Hy' and EM_AC == 'EM_H':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[1],
                                   v_labels[1], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'Hz' and EM_AC == 'EM_H':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[5],
                                   v_labels[5], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'Habs' and EM_AC == 'EM_H':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[6],
                                   v_labels[6], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'Ht' and EM_AC == 'EM_H':
                    plot_component(v_x_q, v_y_q, v_XX, v_YY, vq_plots,
                                   '$(H_x,H_y)$', plot_params, sim_wguide,
                                   ival, comp)
                elif comp == 'ux' and EM_AC == 'AC':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[0],
                                   v_labels[0], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'uy' and EM_AC == 'AC':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[1],
                                   v_labels[1], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'uz' and EM_AC == 'AC':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[5],
                                   v_labels[5], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'uabs' and EM_AC == 'AC':
                    plot_component(v_x, v_y, v_XX, v_YY, v_plots[6],
                                   v_labels[6], plot_params, sim_wguide, ival,
                                   comp)
                elif comp == 'ut' and EM_AC == 'AC':
                    plot_component(v_x_q, v_y_q, v_XX, v_YY, vq_plots,
                                   '$(u_x, u_y)$', plot_params, sim_wguide,
                                   ival, comp)