1.2. How to Produce a User Defined Reader

  1. Write code for all pertinent routines in the library (Unless someone else has done this for you).

    This is of course where the work is done by the user. The word pertinent is used because depending on the nature of the data, some of the routines in the library may be sample or optional routines.

    The source code for a dummy_gold library and for various other working or sample libraries is copied from the installation CD during installation. These will be located in directories under:

    $CEI/ensight242/src/readers


    Note:  The directory following CEI in the path could vary depending on the version of EnSight installed.


    Example 1.1: Basic API 3.0 Readers That Provide a Skeleton Example for a New Reader.

    $CEI/ensight242/src/readers/test3 - structured and unstructured example reader

    $CEI/ensight242/src/readers/test3s - structured example reader

    $CEI/ensight242/src/readers/test3u - unstructured example reader

    $CEI/ensight242/src/readers/test3u_advanced – unstructured advanced reader


    Example 1.2: Sample Library Which Reads Unstructured Binary EnSight Gold Data (Version 2.08 API)

    $CEI/ensight242/src/readers/ensight_gold


    Example 1.3: Sample Library Which Reads C Binary, 3D, Static PLOT3D Data (Version 1.0 API)

    $CEI/ensight242/src/readers/plot3d


    You may find it useful to place the source code for the library you create in this readers area as well, but you are not limited to this location.

    The descriptions of each library routine contained in version 1.0 API, and version 2.0 API, along with version 1.0 API, and version 2.0 API, as well other helps provided in this document, along with the example libraries, should make it possible for you to produce code for your own data reader.

  2. Produce the dynamic shared library.

    This is a compile and load process which varies according to the type of machine that you are running on.

    Example 1.4: Compile test3u Reader on Linux

    Our compile command for our readers is as follows:

    gcc -c -m64 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fPIC -ffloat-store -std=gnu99 -fPIC 
    -Wimplicit -Wreturn-type -Wredundant-decls -g -DARCH64 -DLONG_BIT=64 -DLINUX 
    -DCEIARCH=\"linux_2.6_64\" -DX86_64 -I../libio64/ -I../extern/ -o ./test3u.o test3u.c 

    A considerably simpler reader can be compiled as follows:

    gcc -c -fPIC -I../libio64/ -I../extern/ -o ./test3u.o test3u.c 

    And link as follows:

    gcc  -I/../extern  -shared -o libuserd-test3u.so test3u.o -lm

    Example 1.5: Compile and Link test3u Reador on Windows

    Our compile command for our readers is as follows (you will need to change the include location):

    cl /c /wd4267 /nologo /Zm200  /EHsc  -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE 
    -D_BIND_TO_CURRENT_VCLIBS_VERSION=1 /we4700 /we4553 /we4002 /we4003 /we4715 /we4806  /W3 /wd4305 
    /wd4244 /wd4018 /wd4267 /Od /Z7 /RTC1 /MDd  /D"_CONSOLE" /D"_MBCS" /D"_USE_MATH_DEFINES" 
    -DARCH64 -DWIN32 -D_WIN32_WINNT=0x600  -DWIN64 -DCEIARCH=\"win64\" -I../libio64/ /I...<your location>...
    /apex241/machines/win64/CEI/include 

    A considerably simpler reader can be compiled as follows:

    cl /c /Zm200 /EHsc -DWIN32 -D_WIN32_WINNT=0x600 /Fo./test3u.obj test3u.c 

    Now link as follows (you can leave off everything after the /LIBPATH if you do not need any of our libraries):

    link /LARGEADDRESSAWARE /MACHINE:X64 /MANIFEST  /DLL /DEBUG  /OUT:libuserd-test3u.dll test3u.obj 
    /LIBPATH:….<your location>../apex241/machines/win64/CEI/lib 

    You must then copy your .dll file into the following location (to load when EnSight starts up):

    ….<your location>../ensight241/machines/win64/lib_readers/ 

    If you have platform-specific portions of code in your reader, the build system defines a set of flags which can be used within #ifdef ... #endif regions in your source, as shown in the table below.

    Because the readers are now dynamically opened by EnSight, you may have to include dependent libraries on your link-line to avoid having unresolved symbols. If you are having problems with a reader, start EnSight as ensight -readerdbg and you will get feedback on any problems encountered in loading a reader. If there are unresolved symbols, you need to find the library which contains the missing symbols and link it into your reader by adding it to the example link commands below.

    Once you have created your library, you should place it in a directory of your choice or in the standard reader location: $CEI/ensight242/machines/$CEI_ARCH/lib_readers

    For example, if you created a reader for mydata, you should create the reader libuserd-mydata.so and place the file in your own reader directory (see point 3 below) or in the standard location: $CEI/ensight242/machines/$CEI_ARCH/lib_readers/libuserd-mydata.so

  3. By default EnSight will load all readers found in the directory: $CEI/ensight242/machines/$CEI_ARCH/lib_readers

    Files with names libuserd-X.so (where X is a name unique to the reader) are assumed to be user-defined readers.

    There are two methods which can be used to supplement the default behavior.

    1. A feature which is useful for site-level or user-level configuration is the optional environment variable ENSIGHT20_READER (or legacy ENSIGHT10_READER). This variable directs EnSight to load all readers in the specified reader directory (you should probably specify a full path) before loading the built-in readers. If the same reader exists in both directories (as determined by the name returned by USERD_get_name_of_reader(), NOT by the filename), the locally configured reader will take precedence.

    2. A useful feature for end-users is the use of the libuserd-devel reader. EnSight will search for a reader named libuserd-devel.so (.dll for Windows). This reader can exist anywhere in the library path (see below) of the user. This is useful for an individual actively developing a reader because the existence of a libuserd-devel library will take precedence over any other library which returns the same name from USERD_get_name_of_reader().

    As an example, a site may install commonly used readers in a common location, and users can set the $ENSIGHT20_READER (or legacy $ENSIGHT10_READER variable to access them: setenv ENSIGHT20_READER /usr/local/lib/ereaders

    A user working on a new reader may compile the reader and place it in a directory specified by the library path: cp libuserd-myreader.so ~/lib/libuserd-devel.so setenv <librarypath> ~/lib:$<librarypath>

    The user is responsible for correctly configuring the library path variable in order to make use of the libuserd-devel feature. The library environment variables used are:

    Machine TypeEnvironment Variable to Set
    LinuxLD_LIBRARY_PATH

    As always, Ansys support is available if you need it.

  4. Use the udr_checker tool for help in debugging your user-defined reader.

    The udr_checker.c routine can be used to debug EnSight User-defined readers. It exists because of the difficulty of debugging dynamic shared libraries when you don't have the source for the calling program (EnSight).

    If udr_checker.c is compiled and linked with your reader source code (including access to any libraries needed, and the global_extern.h file), it will exercise most options of you reader, giving feedback as it goes. The resulting executable can be debugged using your favorite debugger. And if you have memory/bounds checking software (such as purify), you can (and should) run it with this executable to make sure that you are not overwriting things. Readers that bash memory will cause problems when run with EnSight!

    You will note that the Makefile provided with the readers in the EnSight distribution have a checker object. If you do a make checker instead of just a make, the checker executable will be produced. You may need to modify these makefiles slightly if the locations of your reader files are different than the normal.

    Once the checker executable exists, you can run the checker program by simply invoking it:

    > checker

    And you will be prompted for the type of information that you provide in the EnSight Data Reader dialog, namely:

              The path

              filename_1

              [filename_2] - Only if your reader uses two fields

              swapbytes flag

              <toggle flags> - Only if your reader implements extra GUI

              <pulldown flags> - one flag value per line

              <field contents> - one field string per line

    There are certain command line options that you can use to control some aspects of the checker program. One of the more useful is the ability to provide the input just described in a file. This is done in this fashion:

    > checker -p <playfile>

    And <playfile> would be a simple ascii file with 3 [0r 4] lines:

              line 1: the path

              line 2: filename_1

              line 3: [filename_2] (if two_fields is TRUE)

              line 3 or 4: 0 or 1, for swapbytes (0 is FALSE, 1 is TRUE)

              remaining lines 0 or 1 for toggle disable enabled

                                  one line for each toggle

                        0 - num_pulldown_values for pulldown choice

                                  one line for each pulldown

                        strings

                                  one line for each field

    Example 1.6: Playfile for an EnSight Gold Reader Casefile (Entitled cube.play) Could Look Something like the Following

              /usr/local/bin/data/ens

              cube.case

              0

    And you would invoke checker as:

    > checker -p cube.play


    Example 1.7: Playfile with Swapbytes 0, Two Enabled Toggles, Three Pulldowns with the Value 0 Chosen and a Single Field "Sample Field Value" Could Look Something like the Following

              /mydirectory/subdir/

              myfile

              0

              1

              1

              0

              0

              0

              sample field value


    Other command line arguments are:

    -server_numberFor checking server number routines. If you use this option, you will be prompted for the total number of servers and the current server number. These will then be used in the calls to the server number routines.
    -gts #For specifying the geometry timestep to test. The default is step 0. The # is the (zero based) time step to read for geometry.
    -vts #For specifying the variable timestep to test. The default is step 0. The # is the (zero based) time step to read for variables. The # is the (zero based) time step to read for variables.