Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dispersion curves and mode analysis #14

Open
hadishamkhi opened this issue Dec 24, 2022 · 5 comments
Open

Dispersion curves and mode analysis #14

hadishamkhi opened this issue Dec 24, 2022 · 5 comments

Comments

@hadishamkhi
Copy link

hadishamkhi commented Dec 24, 2022

Hello,
Congratulations on developing TORCWA!

1- Would you please advise on how to calculate mode dispersion curves of an individual layer, and mode evolution with geometric or materials parameters? Though I am new to the RCWA method, but I understand that computing eigenmodes of individual layer is the first step in the implemented algorithm. So, would it be possible to plot eigenvalues maps (such as Dirac cones) without the need to perform reflection/transmission computations?

2- A follow up on the first question, what is the best approach to track modes coupling evolutions across multiple layers with a geometric tuning in one of them?

My apologies if my questions are not actually issues with the package, but to my understanding providing hints or examples to tackle these questions could be of great help to a broad audience.

Thank you,
Hadi

@kch3782
Copy link
Owner

kch3782 commented Dec 27, 2022

  1. First, if you use the sim.add_layer(...) function in the example, the eigenmodes for each layer are calculated. (If you only need the eigenmode of individual layers, you do not need to use sim.solve_global_matrix, etc.) Each time you use sim.add_layer(...), the number of the layer is given from 0. And for a specific layer_num, eigenvalues and eigenvectors can be obtained with sim.kz_norm[ layer_num] and sim.E_eigvec[layer_num], respectively. kz_norm is normalized to k0 and becomes the effective mode index. However, they are not sorted in ascending or descending order.
    I haven't done this task myself, but I think you can get the eigenvalue map for a certain mode by doing the following. With sweeping according to the wavelength, sorting in descending or ascending order for one of the real part, imaginary part, or absolute value of kz_norm. Then, the eigenvalue for the i-th mode can be obtained among the sorted values.
    However, it does not seem to guarantee that the i-th mode sorted at one wavelength is the same as the [i]th mode sorted at another wavelength. One thing to note is that the eigenvalue is set to have positive imaginary part to ensure decay during propagation. Because of this, if the imaginary part of some eigenvalue is 0 exactly but has a very small value numerically, it is possible to have -2.30 + j0.000001 as an example, so there are cases where the real part becomes negative to make it positive imaginary part. Because of this, it is necessary to find an appropriate sorting method.

  2. After using sim.solve_global_matrix(), you can calculate the coupling coefficient using sim.C[fb][layer_num][m,n]. If fb=0, it is the coefficient for forward incidence, and backward incidence when fb is 1. Using the previous code, the coupling coefficient of the [n]-th E-field Fourier component for the [m]-th positive mode in a specific layer_num is calculated. For the coupling coefficient for the negative mode, use [m+2G] instead of [m], where G is the total number of Fourier orders. However, just like first question, proper sorting is required to ensure that the specific [m]-th mode is the same mode. Using this method, you will be able to track changes in the coupling coefficient.

Thank you.

@hadishamkhi
Copy link
Author

Thank you very much for the detailed answer. I am testing several sorting methods from the simplest like EigenShuffle to a the more elaborated (see for example arxiv.org/abs/2006.14254).

@hadishamkhi
Copy link
Author

hadishamkhi commented Jan 3, 2023

Hello,

I get the following error when I try to compute sim.add_layer(...) before setting the incident angle for the simulation
AttributeError: 'rcwa' object has no attribute 'Kx_norm'

Should it be possible to running sweeps over the incident angle only after calculating the eigenmodes of all layers including the input layer? Assuming the wavelength is kept constant.

    sim = torcwa.rcwa(freq=1/lamb0_now,order=order,L=L,dtype=sim_dtype,device=device)
    sim.add_input_layer(eps=substrate_eps)
    
    layer0_eps = layer0_geometry*pc_eps + (1.-layer0_geometry)     
    sim.add_layer(thickness=layer0_thickness,eps=layer0_eps)
    
    for inc_ind in range(len(inc_ang)):
                 
        inc_now=inc_ang[inc_ind] 
        sim.set_incident_angle(inc_ang=inc_now,azi_ang=azi_ang)
        
        sim.solve_global_smatrix()

would you please advise on a way to reduce the computation time when running multiple sweeps such as the incident waves angle and wavelength?

thank you

@hadishamkhi
Copy link
Author

To further clarify my question on a similar topic, please check out the following
https://optics.ansys.com/hc/en-us/articles/7320004780307

@kch3782
Copy link
Owner

kch3782 commented Jan 3, 2023

A tangential k-vector is determined by the angle of incidence and other k-vectors are defined according to the diffraction order. Afterwards, the eigenmode is calculated according to these k-vectors. Since the add_layer function perform the eigenmode calculation, the angle must be set before and the set_incident_angle function must come first. Depending on the wavelength and angle, the eigenvalue and eigenmode are different. Also, due to the GPU memory issue, we couldn't verify the computation time reduction according to vectorization, so we have to create individual simulations for now. So, for now, I think you should use the following code for sweeping over incident angle.

for inc_ind in range(len(inc_ang)):
    inc_now = inc_ang[inc_ind]

    sim = torcwa.rcwa(freq=1/lamb0_now,order=order,L=L,dtype=sim_dtype,device=device)
    sim.add_input_layer(eps=substrate_eps)
    sim.set_incident_angle(inc_ang=inc_now,azi_ang=azi_ang)

    layer0_eps = layer0_geometry*pc_eps + (1.-layer0_geometry)     
    sim.add_layer(thickness=layer0_thickness,eps=layer0_eps)

    sim.solve_global_smatrix()

Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants