Skip to main content
Solved

How do I 'tell' Zemax to use the [gradient] index during refraction?


Ivair.Gontijo

   I created a DLL to model a gradient index surface and while it is working, the modeling results are very similar to a standard surface. It seems that somehow Zemax is not using the gradient index during the refraction process. I have been investigating what I am doing wrong and got more confused.  Your help will be greatly appreciated! :-)

   Looking into the example from /zemax/dll/surfaces/us_grin1.c, the refractive indices used for refraction in case 5 are FD->n1 and FD->n2, which are the indices before and after the GRIN surface. In case 6, which is where the index and its derivatives are defined, the refractive index is calculated and the assignment UD->index = index is made, as well as the dn/dx, dn/dy and dn/dz.

   So, I am a bit confused:

  1. Which refractive index is used during refraction, UD->index or FD->n2? I was expecting that I would use UD->index, but that is not what happens in case 5. How does Zemax ‘know’ that it is dealing with a gradient index material then?
  2. I am assuming that the ‘material column’ should be left blank when the surface is a GRIN (and the GRIN parameter columns should be populated of course). Is this correct? 
  3. What value is passed to FD->n2 and the refraction function call, if the material column is blank?

Thank you!

 

  • Should I leave the material column blank?

Best answer by David.Nguyen

@Ivair.Gontijo 

 

Apologies if I wasn’t clear.

Let me try to phrase it differently.

The DLL is not a linear piece of code that is executed from top to bottom like a script. Instead, OpticSutdio makes calls to the function inside the DLL whenever it needs to know some data. There are many calls to the DLL functions happening in the background. The functions defined in the DLL have parameters, and OpticStudio uses those parameters to specify what it wants.

For example, when you set up the User Defined surface OpticStudio will want to populate the default values of the LDE parameters. In this case, it will call the DLL and specify only case 7 (or 8 I don’t remember) to get and display those default values.

Similarly when OpticStudio needs to calculate a refraction at an interface, it will make several calls to the DLL, asking for the refractive index (case 6) and then performing the actual refraction (case 5).

Within your GRIN material, multiple refractions needs to be calculated (at every Delta T), for each refraction, OpticStudio calculates n1 and n2 (the indices before and after the interface) using case 6, and they become available as n1, and n2 in case 5. But you don’t see it happening because it happens on OpticStudio side.

If you want to be absolutely sure, you can run a single raytrace through your surface and analyze the ray segment direction (I know you know how to do it because you studied Welford’s book :).

You could also try to run the DLL in debug mode,

https://support.zemax.com/hc/en-us/articles/1500005576802-How-to-debug-a-DLL-or-EXE.

Or you can also try to print some data to a file within the DLL.

Does that help?

Take care,

 

David

View original
Did this topic help you find an answer to your question?

5 replies

David.Nguyen
Luminary
Forum|alt.badge.img+2

@Ivair.Gontijo 

 

Without looking at your code, it might be difficult to say. But here are some elements of answer for you.

First, there’s a distinction to be made between UD, and FD. UD stands for User Data and it is what the DLL should compute (behavior you can alter) and return to OpticStudio. FD stands for Fixed Data, and it is available from within the DLL but cannot be changed.

How does Zemax “know” that it is a gradient index material? Line 47 of us_grin1.c (general Case 0):

case 2:
    /* ZEMAX wants to know if this surface is a gradient index media */
    /* it is. */
    strcpy(UD->string, "1");
    break;

Regarding 2. You are right. Once Zemax “knows” its a gradient index material, it won’t look at the Materials column anymore (instead it uses Case 6). Whether you type something in the Materials column or not shouldn’t make any difference (it is just ignored).

Regarding 3. It should be the refractive index value calculated in Case 6 and this is done at every step Delta T.

Does that help?

Take care,

 

David


Ivair.Gontijo

Thank you ​@David.Nguyen for the reply above, I appreciate your kindness and help! Some confusion still remains regarding cases 5 and 6 in the example “us_grin1.c”:

  • Note that in case 6 there is no function call to ‘Refract(...)’, the refraction function. In case 6 the UD->index and UD->dn/dx, dn/dy and dn/dz are calculated and they become available to Zemax, but it is not clear how/where they are used.
  • Refraction only happens in case 5, where a real ray trace is done. The weird/confusing thing is that it does not use the new index calculated in case 6. It uses FD->n2 (see below) which, as you pointed out, is Fixed Data, that cannot be changed by the user.  I am guessing that FD->n2 used in refraction in case 5 normally comes from the material column. How is the GRIN refraction being calculated, if the material column is empty and UD->index is not used below?
  •  


David.Nguyen
Luminary
Forum|alt.badge.img+2
  • Luminary
  • 1141 replies
  • Answer
  • July 23, 2025

@Ivair.Gontijo 

 

Apologies if I wasn’t clear.

Let me try to phrase it differently.

The DLL is not a linear piece of code that is executed from top to bottom like a script. Instead, OpticSutdio makes calls to the function inside the DLL whenever it needs to know some data. There are many calls to the DLL functions happening in the background. The functions defined in the DLL have parameters, and OpticStudio uses those parameters to specify what it wants.

For example, when you set up the User Defined surface OpticStudio will want to populate the default values of the LDE parameters. In this case, it will call the DLL and specify only case 7 (or 8 I don’t remember) to get and display those default values.

Similarly when OpticStudio needs to calculate a refraction at an interface, it will make several calls to the DLL, asking for the refractive index (case 6) and then performing the actual refraction (case 5).

Within your GRIN material, multiple refractions needs to be calculated (at every Delta T), for each refraction, OpticStudio calculates n1 and n2 (the indices before and after the interface) using case 6, and they become available as n1, and n2 in case 5. But you don’t see it happening because it happens on OpticStudio side.

If you want to be absolutely sure, you can run a single raytrace through your surface and analyze the ray segment direction (I know you know how to do it because you studied Welford’s book :).

You could also try to run the DLL in debug mode,

https://support.zemax.com/hc/en-us/articles/1500005576802-How-to-debug-a-DLL-or-EXE.

Or you can also try to print some data to a file within the DLL.

Does that help?

Take care,

 

David


Ivair.Gontijo

Yes ​@David.Nguyen, that is very helpful! In summary, FD->n2 is “Fixed Data” from the user’s perspective only. When Zemax is dealing with a GRIN surface, it will update this value by calling the DLL with case 6 to request the refractive index and making FD->n2 = UD->index. This in fact allows the software to use the same Refract(..) function in all cases, which is neat!

Thanks again!


David.Nguyen
Luminary
Forum|alt.badge.img+2

@Ivair.Gontijo 

 

That is an excellent summary. And it also prevents users from accidentally modifying FD->n1 and FD->2 during refraction.

Take care,


David


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings