# Simulate 2D diffraction grating using customized diffractive DLL

• 9 replies
• 1920 views

Userlevel 6
+2
• Zemax Staff
• 125 replies

In OpticStudio, currently we only support one dimensional grating. However, it's not difficult to simulate 2D grating. Here we will show an example using diffractive DLL.

You may compile it with the instructions or use the DLL file attached to this article.

Before we start, here are some articles for required background knowledge that we will not repeat in this forum post.

Let's simply open the attached cpp file and observe how it works in non-sequential mode.

This example is mainly modified from the built-in sample \Documents\Zemax\DLL\Diffractive\diff_samp_1.c

To compile the program as C++ code. We package the functions with extern 'C'.

In this example, we only want to return diffraction ray direction and its relative intensity. So setting data[31] = 1 is enough. If we also know the polarization state or the full eletric field value, we can use data[31] = 2.

Here assumes we want to simulate 5 orders in x and y direction, so there should be totally 25 orders from (-5,-5) to (5,5). Because currently OpticStudio only considers the diffractive DLL simulates 1D grating, we need to represent the 2D orders in 1D. Here we will only consider orders from 0 to 24, which represents (-2,-2) to (2,2). If OpticStudio requests orders other than this range, we return -1, which will result in an geometric error in OpticStudio. For this reason, when using this DLL, the Start Order should be 0 and Stop Order should be 24 in OpticStudio.

Then, we can decompose the 1D order into corresponding 2D orders.

When data[31] = 1, we need to return the value for phase derivative and phase accumulation.

Note the phase derivative is same as what we described in page 3 in this forum post: How diffraction ray-tracing is calculated | Zemax Community

The phase (variable 'P') is simply accumulation of the phase assuming the phase at surfase vertex is zero.

In UserParamNames(), we define the efficiency for each diffraction order.

Then simply read it to data[30], which is the relative intensity reported to OpticStudio!

### 9 replies

Userlevel 6
+2

Attached is a example for user defined surface used in sequential mode. This is modified from the built-in us_grate.c. The concept is same as above, but with one main difference: there need to be two parameters Order X and Order Y to let users explicitly specify what order to trace. This is because in sequential mode, only one path can be traced at once.

Only two parts are changed.

1. Add two parameters for x directional periodicity.

2. Code added to consider for another periodicity in x direction.

T,M becomes Tx,Ty,Mx,My.

Adding code for dpdx. Just mimics dpdy and that's it!

Userlevel 7
+3

Gotta say Michael, you are doing some seriously good work here. Well done!

Userlevel 6
+2

In OpticStudio, currently we only support one dimensional grating. However, it's not difficult to simulate 2D grating. Here we will show an example using diffractive DLL.

You may compile it with the instructions or use the DLL file attached to this article.

Before we start, here are some articles for required background knowledge that we will not repeat in this forum post.

Let's simply open the attached cpp file and observe how it works.

This example is mainly modified from the built-in sample \Documents\Zemax\DLL\Diffractive\diff_samp_1.c

To compile the program as C++ code. We package the functions with extern 'C'.

In this example, we only want to return diffraction ray direction and its relative intensity. So setting data[31] = 1 is enough. If we also know the polarization state or the full eletric field value, we can use data[31] = 2.

Here assumes we want to simulate 5 orders in x and y direction, so there should be totally 25 orders from (-5,-5) to (5,5). Because currently OpticStudio only considers the diffractive DLL simulates 1D grating, we need to represent the 2D orders in 1D. Here we will only consider orders from 0 to 24, which represents (-5,-5) to (5,5). If OpticStudio requests orders other than this range, we return -1, which will result in an geometric error in OpticStudio. For this reason, when using this DLL, the Start Order should be 0 and Stop Order should be 24 in OpticStudio.

Then, we can decompose the 1D order into corresponding 2D orders.

When data[31] = 1, we need to return the value for phase derivative and phase accumulation.

Note the phase derivative is same as what we described in page 3 in this forum post: How diffraction ray-tracing is calculated.

The phase (variable 'P') is simply accumulation of the phase assuming the phase at surfase vertex is zero.

In UserParamNames(), we define the efficiency for each diffraction order.

Then simply read it to data[30], which is the relative intensity reported to OpticStudio!

Hi,Michael!

I meet a problem that when setting  data[31] = 2 in the built-in sample \Documents\Zemax\DLL\Diffractive\diff_samp_1.c and output the new DLL ,  Diffraction Grating with the new DLL in which data[31] = 2 can not receive beam rays, namely the light beams can not reach the diffraction grating.

Why it become like this?

zhouqing

Userlevel 6
+2

Hi Zhouqing,

Thank you for reply. Setting data[31] = 2 should be not a problem. The problem probably happens at your other code. Could you send your question to support inbox so we can help to further look at your question? Thank you!

Michael

I have send my question to the mailbox Zemax Community <community@zemax.com>. In case of encountering problems when sending the email，I also present my questions in more detail as below:
Firstly, I just change the code data[31] = 1 to data[31] = 2  in the built-in sample \Documents\Zemax\DLL\Diffractive\diff_samp_1.c and output the new DLL.
When I use the new DLL in Diffraction Grating in NSC mode, the light beam can not reach the grating. Maybe there are something wrong when I changed the code in the built-in sample \Documents\Zemax\DLL\Diffractive\diff_samp_1.c.

Then I review the DLL in ZEMAX Knowledgebase(KBA), there are some keys as shown below:

According to the above content, If I set the code data[31] = 2  , then the data[35]~[37], and data [40]~[45] should also be calculated or set. For the further code setting of  data[35]~[37] and data [40]~[45] , I still feel  a bit difficult to input the perfect new codes as I am not familiar with the C++ and ZEMAX Programming logic for Diffractive DLL.

If Michael could give me some help or suggestions for the above tricky situation as I meet.

Zhouqing

Userlevel 6
+2

Hi Zhouqing,

I’m sorry for confusion, but could you try to create a case via the following link.

https://support.zemax.com/hc/requests/new

Or, you can also send the question to the support box: zemax.support@ansys.com

Both method will reach to the same team. Using the link is suggested as you will be able to check the status of the tickets. Please note you will need to create a Zemax account in order to open a ticket. Please let us know if you have any issue. Thank you.

Thank you, Michael!

I have send my question to the support box: zemax.support@ansys.com

At the same time, I also present my questions again as below:

I just change the code data[31] = 1 to data[31] = 2  in the built-in sample \Documents\Zemax\DLL\Diffractive\diff_samp_1.c and output the new DLL.When I use the new DLL in Diffraction Grating in NSC mode, the light beam can not reach the grating. Maybe there are something wrong when I changed the code in the built-in sample \Documents\Zemax\DLL\Diffractive\diff_samp_1.c.

Then I review ” Custom DLLs in OpticStudio: An overview of user-defined surfaces, objects, and other DLL types”in ZEMAX knowledgebase (KBA), there are some keys as shown below:

“ If data[31] equals 2, it must also calculate data 35-45, the complete output ray data. The DLL should return 0 if successful, and -1 if it encountered an error. For a complete description of all the data items passed between ZOS and the Diffraction DLL, please see the example {Zemax}\DLL\Diffraction\diff_samp_1.c.

Note when the data[31] is 2, the power of diffracted ray is mainly calculated by the returned field data in data[40-45]. However, the data[30] can still affect the ray-tracing in two ways. One is that OpticStudio will use data[30] for estimating the Lost Energy, which shows in the Ray Trace dialog, during raytracing. One is that the diffractive ray will stop tracing if the value in data[30] is smaller than Minimum Relative Ray Intensity in the System Explorer.

According to the above content,  If I set the code data[31] = 2  , then the data[35]~[37], and data [40]~[45] in the built-in sample diff_samp_1.c should also be calculated. For the further code setting of  data[35]~[37] and data [40]~[45] , I still  feel  a bit difficult to write the perfect new codes as I am not familiar with the C++ and ZEMAX Programming logic for Diffractive DLL.

If Michael could give me some help or suggestions for the above tricky situation as I present.

Zhouqing

Thanks for the tutorial Michael, very informative.

I have tried to implement a similar code that the one you provide here but to also analize the reflection modes of a simple 2D grating. In my case I restricted the Tranmission and Reflection modes to (-1,-1) → (1,1).

In my case the call for input parameters looks like this:

I have tried to modify data[11] value to accomodate either tranmission and reflection modes asking which mode is being calculated as follows:

but this proven not to work. Zemax only calculated the transmissive modes and all the reflection modes are there but as simple reflection from a glass surface.

Could you please give me a hint on how to implement this properly?

Thank you!