Source code for cemd_metasurf.reflec_transm.reflec_transm

"""
Here the class ReTr for calculating refletion and tranmission can be found.
"""

import numpy as np	
from . import rt_functions as rtf

[docs]class ReTr(object):
[docs] def calc_rt_kxky(self, my_bloch = None, ind_ini = 0, n=0,m=0): """ Calculates the reflectance (R) and transmitance (T) for a transverse electric (TE) or transverse magnetic (TM) incoming plane wave at all Bloch waves stored in array_k_gb. If a my_bloch is given, R and T will be calculated over this values, by calculating first the depolarization Green function (gb). Consider that in this case, the value of ind_ini is set to the size of the previous self.array_k_gb.shape, in order of only calculating R and T for the given my_bloch. Also, clear.array_k_rt() and clear.array_k_gb() are called at the end if my_bloch is given. The values are stored in "array_k_rt", with dimension along "axis = 1" (columns) are: 1. k 2. kx 3. ky 4. n 5. m 6. r_tm 7. r_te 8. t_tm 9. t_te :param my_bloch: The object with the information of the wavevectos. By default it is not needed, using the wavevetors stored in self.array_k_gb. If a my_bloch is used, R and T would be calculated over these values. :type my_bloch: classes.BlochWavevector :param ind_ini: From which value of the stored gb start to calculate R and T (try to generilized to a range). Only used is "my_bloch = None". :type ind_ini: Int :param n: Diffractive order along x-axis. :type n: Int :param m: Diffractive order along the other axis defined by the lattice. :type m: Int """ x, y, z = self.get_unit_cell() if type(my_bloch) != type(None): if type(self.array_k_gb) != type(None): ind_ini = self.array_k_gb.shape[0] self.calc_gb_kxky(my_bloch, append_k_gb = True) for i in range(ind_ini,self.array_k_gb.shape[0]): self.k, self.kx, self.ky = self.array_k_gb[i,0:3].real self.set_alpha() if type(x) == np.float64: self.gb_kxky = self.array_k_gb[i,3:].reshape(6,6) self.rt_kxky_nm = rtf.calc_rt(self,n,m) else: return print("the case of complex unit cells are not implemented") k_rt = np.append([self.k,self.kx,self.ky,n,m],self.rt_kxky_nm.reshape(1,-1)).reshape(1,-1) if type(self.array_k_rt) == type(None): self.array_k_rt = k_rt else: self.array_k_rt = np.append(self.array_k_rt,k_rt, axis=0) if type(my_bloch) != type(None): self.clean_array_k_gb() self.clean_array_k_rt()
[docs] def clear_array_k_rt(self): """ Clear the stored reflectance and transmitance. """ self.array_k_rt = None
[docs] def clean_array_k_rt(self): """ Clean the stored reflectance and transmitance. Remove repeted rows and sort by k -> kx -> ky -> n -> m. """ sort_array_k_rt = self.array_k_rt[ np.lexsort( (self.array_k_rt[:,0], self.array_k_rt[:,1], self.array_k_rt[:,2], self.array_k_rt[:,3], self.array_k_rt[:,4] ) ) ] self.array_k_rt = np.unique(sort_array_k_rt, axis=0)
[docs] def get_rt(self): """ Return reflectance and transmitance. For konwing "(k, kx, ky)" and "(n, m)" look self.array_k_rt. :return: tuple with R and T """ r_tm = self.array_k_rt[:,5] r_te = self.array_k_rt[:,6] t_tm = self.array_k_rt[:,7] t_te = self.array_k_rt[:,8] return r_tm, r_te, t_tm, t_te
[docs] def calc_rt_complex_kxky(self, my_bloch = None, ind_ini = 0): """ Calculates the complex specular reflection (r) and transmissio (t) for a transverse electric (TE) or transverse magnetic (TM) incoming plane wave at all Bloch waves stored in array_k_gb. If a my_bloch is given, r and t will be calculated over this values, by calculating first the depolarization Green function (gb). Consider that in this case, the value of ind_ini is set to the size of the previous self.array_k_gb.shape, in order of only calculating r and t for the given my_bloch. Also, clear.array_k_rt_complex() and clear.array_k_gb() are called at the end if my_bloch is given. The values are stored in "array_k_rt_complex", with dimension along "axis = 1" (columns) are: 1. k 2. kx 3. ky 4. r_tm 5. r_te 6. t_tm 7. t_te :param my_bloch: The object with the information of the wavevectos. By default it is not needed, using the wavevetors stored in self.array_k_gb. If a my_bloch is used, R and T would be calculated over these values. :type my_bloch: classes.BlochWavevector :param ind_ini: From which value of the stored gb start to calculate R and T (try to generilized to a range). Only used is "my_bloch = None". :type ind_ini: Int :param n: Diffractive order along x-axis. """ x, y, z = self.get_unit_cell() if type(my_bloch) != type(None): if type(self.array_k_gb) != type(None): ind_ini = self.array_k_gb.shape[0] self.calc_gb_kxky(my_bloch, append_k_gb = True) for i in range(ind_ini,self.array_k_gb.shape[0]): self.k, self.kx, self.ky = self.array_k_gb[i,0:3].real self.set_alpha() if type(x) == np.float64: self.gb_kxky = self.array_k_gb[i,3:].reshape(6,6) self.rt_kxky_complex = rtf.calc_rt_complex(self) else: return print("the case of complex unit cells are not implemented") k_rt = np.append([self.k,self.kx,self.ky],self.rt_kxky_complex.reshape(1,-1)).reshape(1,-1) if type(self.array_k_rt_complex) == type(None): self.array_k_rt_complex = k_rt else: self.array_k_rt_compex = np.append(self.array_k_rt_complex,k_rt, axis=0) if type(my_bloch) != type(None): self.clean_array_k_gb() self.clean_array_k_rt_complex()
[docs] def clear_array_k_rt_complex(self): """ Clear the stored reflectance and transmitance. """ self.array_k_rt_complex = None
[docs] def clean_array_k_rt_complex(self): """ Clean the stored reflectance and transmitance. Remove repeted rows and sort by k -> kx -> ky. """ sort_array_k_rt_complex = self.array_k_rt_complex[ np.lexsort( (self.array_k_rt_complex[:,0], self.array_k_rt_complex[:,1], self.array_k_rt_complex[:,2]) ) ] self.array_k_rt_complex = np.unique(sort_array_k_rt_complex, axis=0)
[docs] def get_rt_complex(self): """ Return reflectance and transmitance. For konwing "(k, kx, ky)" look self.array_k_rt_complex. :return: tuple with r and t """ r_tm = self.array_k_rt_complex[:,3] r_te = self.array_k_rt_complex[:,4] t_tm = self.array_k_rt_complex[:,5] t_te = self.array_k_rt_complex[:,6] return r_tm, r_te, t_tm, t_te
[docs] def calc_rt_pol_kxky(self, my_bloch = None, ind_ini = 0, pol_tm = 1, pol_te = 1j, n=0,m=0): """ Calculates the de reflectance (R) and transmitance (T) at all Bloch waves stored in array_k_gb for a incoming plane wave with polarization defiend by the parameters pol_tm and pol_te: :math:`\phi_{0} = \phi_{TM}\mathrm{pol_tm} + \phi_{TE}\mathr{pol_te}`. Thus, by default the incident is a circular polarized wave (pol_tm = 1, pol_te = 1j). If a my_bloch is given, R and T will be calculated over this values, by calculating first the depolarization Green function (gb). Consider that in this case, the value of ind_ini is set to the size of the previous self.array_k_gb.shape, in order of only calculating R and T for the given my_bloch. Also, clear.array_k_rt_pol() and clear.array_k_gb() are called at the end if my_bloch is given. The values are stored in "array_k_rt", with dimension along "axis = 1" (columns) are: 1. k 2. kx 3. ky 4. pol_tm 5. pot_te 6. n 7. m 8. r_pol 9. t_pol :param my_bloch: The object with the information of the wavevectos. By default it is not needed, using the wavevetors stored in self.array_k_gb. If a my_bloch is used, R and T would be calculated over these values. :type my_bloch: classes.BlochWavevector :param ind_ini: From which value of the stored gb start to calculate R and T (try to generilized to a range). Only used is "my_bloch = None". :type ind_ini: Int :param pol_tm: TM amplitude. :type pol_tm: complex :param pol_te: TE amplitude. :type pol_te: complex :param n: Diffractive order along x-axis. :type n: Int :param m: Diffractive order along the other axis defined by lattice. :type m: Int """ x, y, z = self.get_unit_cell() if type(my_bloch) != type(None): if type(self.array_k_gb) != type(None): ind_ini = self.array_k_gb.shape[0] self.calc_gb_kxky(my_bloch, append_k_gb = True) for i in range(ind_ini,self.array_k_gb.shape[0]): self.k, self.kx, self.ky = self.array_k_gb[i,0:3].real self.set_alpha() if type(x) == np.float64: self.gb_kxky = self.array_k_gb[i,3:].reshape(6,6) self.rt_kxky_nm = rtf.calc_rt_pol(self,pol_tm,pol_te,n,m) else: return print("the case of complex unit cells are not implemented") k_rt = np.append([self.k,self.kx,self.ky,pol_tm,pol_te,n,m],self.rt_kxky_nm.reshape(1,-1)).reshape(1,-1) if type(self.array_k_rt_pol) == type(None): self.array_k_rt_pol = k_rt else: self.array_k_rt_pol = np.append(self.array_k_rt_pol,k_rt, axis=0) if type(my_bloch) != type(None): self.clean_array_k_gb() self.clean_array_k_rt_pol()
[docs] def clear_array_k_rt_pol(self): """ Clear the stored reflectance and transmitance. """ self.array_k_rt_pol = None
[docs] def clean_array_k_rt_pol(self): """ Clean the stored reflectance and transmitance. Remove repeted rows and sort by k -> kx -> ky -> pol_tm -> pol_te -> n -> m. """ sort_array_k_rt_pol = self.array_k_rt_pol[ np.lexsort( (self.array_k_rt_pol[:,0], self.array_k_rt_pol[:,1], self.array_k_rt_pol[:,2], self.array_k_rt_pol[:,3], self.array_k_rt_pol[:,4], self.array_k_rt_pol[:,5], self.array_k_rt_pol[:,6] ) ) ] self.array_k_rt_pol = np.unique(sort_array_k_rt_pol, axis=0)
[docs] def get_rt_pol(self): """ Return reflectance and transmitance. For konwing "(k, kx, ky)", "(pol_tm, pol_te)" and "(n, m)" look self.array_k_rt_pol. :return: tuple with R and T """ r_pol = self.array_k_rt_pol[:,7] t_pol = self.array_k_rt_pol[:,8] return r_pol, t_pol