ZEMAX Users' Knowledge Base - http://www.zemax.com/kb
How to Create a User-Defined Solve
http://www.zemax.com/kb/articles/101/1/How-to-Create-a-User-Defined-Solve/Page1.html
By Nam-Hyong Kim
Published on 31 July 2006
 

This article shows how to use the ZPL solve feature to create a user-defined solve. The steps involved are illustrated using  an included sample file. The sample file can be downloaded from the last page of this article.


Creating a solve using a ZPL macro
Solves are functions which actively adjust specific values in an editor. Solves can be specified on curvatures, thicknesses, glasses, semi-diameters, conics, parameters, TCE values, and Extra Data Editor values. Solves are set by double clicking on the cell you wish to place the solve on.

There are many solves supplied with ZEMAX. For the list of available solve types, refer to the "Solves" chapter in the user manual. An arbitrary solve can be defined via the ZEMAX Programming Language (ZPL). The solve window, accessed by double clicking on a parameter in the editor, has a "ZPL Macro" option (see below). Once the macro describing the solve has been created and placed in the {root}/ZEMAX/MACROS directory, the name of that macro can be entered to the right of the "Macro:" cell in the solve window.



As a simple example, we will require a non-sequential object to be 10 mm behind the end of another non-sequential object. This requires us to calculate the length of the previous object, and to use this to position the second object.

In the attached non-sequential sample file, the first object is a rectangular Compound Parabolic Concentrator object. This object has a maximum length defined as a parameter in the NSC Editor. If we could guarantee that the object would always be this maximum length, we could simply use a pick-up solve with an offset to position object 2. However, the real length may be smaller than the maximum length parameter, so we must calculate the real length and use this value. Also, as this is a rectangular CPC object, the real length may be different for the x and y slices: we must choose the smaller of the two. This is an ideal problem fo rthe macro solve!

The length  "L" of the CPC is given by the formula in the manual (in the chapter on non-sequential components, section on non-sequential objects, sub-section on compound parabolic concentrator objects) as:


Since this is a Rectangular CPC object, there are two associated length values; X and Y. The smaller of the two lengths is then taken as the length of the CPC by ZEMAX, unless this length is larger than the "Length" parameter. In that case, the length is the value of the "Length" parameter. The macro should therefore calculate the X and Y length of the CPC object by using the formula above, pick the smaller of the two values, add 10mm offset and return that value to the Z Position parameter of the Rectangle object. If the smaller length between X and Y is still larger than the "Length" parameter value, then the macro should add 10mm offset to the "Length" parameter value and return this value instead.
 
The REC_CPC.ZPL macro is shown below.




The keyword SOLVERETURN is used to pass the desired value back to the NSC Editor.

Place the macro in the {zemaxroot}/MACROS folder and click "Macros > Refresh Macro List" in the main menu.

On the Z Position parameter of Rectangle object #2 place the following solve and click OK.



The Editor will show "Z" next to the parameter, indicating that ZPL solve has been placed on that parameter.



Toggle between the 2 configurations using  the Ctrl-A keystroke; the Y angle parameter of the Rectangular CPC object will change betwee 20 and 40 degrees, hence changing the length of the object. The Z position value of object #2 will change automatically to always place this object 10mm behind the end of the CPC object.



Tricks and Gotchas

Macro solves are very general, allowing virtually any computation to be used to determine a solve value. All functions and keywords supported by ZPL are available. There are no differences between ZPL macros executed from the macro menu or executed as a solve. However, you should take care when writing ZPL solves. For example:

  • Many ZPL keywords and some functions should not be used in a macro solve. For example, calling "UPDATE" from the solve will update all solves, which will invoke the macro again, resulting in an infinite loop. Other keywords, such as INPUT, will require the user to enter data every time the solve is called, which may be an enormous number of times.
  • Keywords that set values in the editors or create merit functions should not be used.
  • Macro solves should never depend upon data in the editors that is subsequent to the solve; as this may also create erroneoeus data if the solve is called first and then the source data is modified by a separate, subsequent solve.
  • In general, macro solves should be kept short and simple, avoid lengthy computations, and should not make modifications of any lens data. 
  • Note that if you use a macro solve to compute a radius of curvature in the Lens Data Editor, that all solves for this parameter compute curvature, not radius of curvature. The solve should return the inverse of the radius of curvature for this parameter.
  • You are responsible for error-checking the data returned by the macro. For example, if your macro calls a RAYTRACE function to evaluate a ray parameter on surface 5, you should call the RAYE() function to ensure that no error has occurred. For example, the ray may TIR at an earlier surface, or have have hit an aperture. If an error occurs, you should exit the macro without calling SOLVERETURN. The following code snippet gives an example of how to test for errors. Make sure you do not return a value via SOLVERETURN if an error occurs. This is particularly important during optimization.

ZEMAX makes no attempt to qualify or validate the solve macro. This feature offers great power and flexibility, but must be used carefully.