\documentclass[12pt]{beamer}
\input{BEAMERoptions.tex}

% ----- Packages and libraries ----- %
\usepackage[T1]{fontenc}                                % cut/paste and search with "_"
\usepackage[english]{babel}
\usepackage{graphics}
\usepackage{verbatim}
\usepackage{times}
\usepackage{graphicx}
\usepackage{epsfig}
\usepackage{subfigure}
\usepackage{amssymb}
\usepackage{amsmath, amsfonts}
\usepackage{amsthm}
\usepackage{color}
\usepackage{alltt}
\usepackage{anyfontsize}
\usepackage{fancyvrb}
\usepackage{tikz}
   \usetikzlibrary{shapes, arrows, shadows}

\newcommand{\Frametitle}[1]{\frametitle{\includegraphics[width=0.25in]{esp_logo.png}
      \hspace{0.05in} #1}}

\newcommand{\FrameTitle}[1]{\frametitle{\includegraphics[width=0.3in]{caps_logo.png}
      \hspace{0.05in} #1}}

\setbeamertemplate{navigation symbols}{}
\setbeamertemplate{caption}[numbered]

%============================
% command to repeate a ~ n-times
%============================
\newcount\myloopcounter

\newcommand{\spaces}[1][10]{%
  \myloopcounter0% initialize the loop counter
  \loop\ifnum\myloopcounter < #1 % Test if the loop counter is < #1
  ~%
  \advance\myloopcounter by 1 %
  \repeat % start again
}
%============================

% ----- Presentation information ----- %
\title[UDP/UDF Programming -- Basics]{
\includegraphics[width=1.0in]{esp_logo.png}\\
Engineering Sketch Pad\\
UDP/UDF Programming -- UDP Basics\\[0.02in]
For {\tt ESP} Rev 1.28}

\author[Dannenhoffer]{
John F. Dannenhoffer, III \\
  {\footnotesize \textcolor{blue}{john@geocentrictech.com} \\[-0.03in]
    Geocentric Technologies LLC}
}

\date[July 2025]{}

% ----- Document follows ----- %

\begin{document}

\begin{frame}
  \titlepage
\end{frame}

\begin{frame}
  \Frametitle{Overview}

  \begin{itemize}
  \item Differences between UDPs and UDFs
  \item How UDP/UDFs are used in ESP
  \item Anatomy of directory {\tt udpTemplate}
  \item Steps for generating UDP/UDFs
  \item Line-by-line description of {\tt template.c}
  \item Exercise1
  \end{itemize}
\end{frame}

\begin{frame}
  \Frametitle{Differences Between UDPs and UDFs}

  \begin{itemize}
  \item Users can add their own user-defined primitives (UDPs)
    \begin{itemize}
    \item creates a single* Body
    \item do not consume any Bodys from the Stack
    \item are written in C, C++, or FORTRAN and are compiled
    \item can be written either top-down or bottom-up or both
    \item have access to the entire suite of methods provided by
      {\tt EGADS}
    \item are coupled into {\tt ESP} dynamically at run time
    \end{itemize}
  \item Users can add their own user-defined functions (UDFs)
    \begin{itemize}
    \item are the same as UDPs, except they consume one or more
      Bodys from the Stack
    \end{itemize}
  \item Creating UDPs and UDFs involve (almost) the same process
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Calling a UDP/UDF (1)}

  \begin{itemize}
  \item UDP/UDFs are called with a {\tt UDPRIM} statement
    \begin{footnotesize}
\begin{verbatim}
UDPRIM    $primtype $argName1 argValue1 \
                    $argName2 argValue2 \
                    $argName3 argValue3 \
                    $argName4 argValue4
\end{verbatim}
    \end{footnotesize}
  \item {\tt \$primtype} must start with a letter
  \item At most 4 name-value pairs can be specified on the {\tt
      UDPRIM} statement
    \item More name-value pairs can be specified in any number of
      {\tt UDPARG} statements that precede the {\tt UDPRIM} statement
    \begin{footnotesize}
\begin{verbatim}
UDPARG    $primtype $argName1 argValue1 \
                    $argName2 argValue2 \
                    $argName3 argValue3 \
                    $argName4 argValue4
\end{verbatim}
    \end{footnotesize}
  \item name-value pairs are processed in order (with possible
    over-writing)
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Calling a UDP/UDF (2)}

  \begin{itemize}
  \item For UDP/UDFs that read an external file, one can use \verb+<<+ to
    tell {\tt ESP} to create a file from the following lines, up to a
    line that starts with \verb+>>+
  \item For example:
    \begin{footnotesize}
\begin{verbatim}
UDPRIM    editAttr  filename <<  verbose 1
        NODE ADJ2FACE tagType=spar tagIndex=1
        AND  ADJ2FACE tagType=lower
        AND  ADJ2EDGE tagType=root
        SET           capsConstraint=pointConstraint1
>>
SET       A  10
\end{verbatim}
    \end{footnotesize}
      has two Branches ({\tt UDPRIM} and {\tt SET})
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{{\tt UDPARG} and {\tt UDPRIM} Examples}

  \begin{itemize}
  \item The following generate identical Boxes
    \begin{footnotesize}\begin{verbatim}
     UDPRIM box dx 1 dy 2 dz 3
\end{verbatim}
  \end{footnotesize}
  \item and
    \begin{footnotesize}\begin{verbatim}
     UDPARG box dx 1
     UDPRIM box dy 2 dz 3
\end{verbatim}
  \end{footnotesize}
  \item and
    \begin{footnotesize}\begin{verbatim}
     UDPARG box dx 11 dy 22 dz 33
     UDPRIM box dx 1  dy 2  dz 3
\end{verbatim}
  \end{footnotesize}
  \item and
    \begin{footnotesize}\begin{verbatim}
     UDPARG box dx 1
     UDPARG box dy 2
     UDPARG box dz 3
     UDPRIM box
\end{verbatim}
  \end{footnotesize}
  \end{itemize}
\end{frame}

\begin{frame}
  \Frametitle{Return Values from UDP/UDFs}

  \begin{itemize}
  \item Some UDP/UDFs return values to the calling script
  \item The returned values have names that are prepended by two
    at-signs (for example: {\tt volume} in the UDP/UDF is available as
    {\tt @@volume} after the {\tt UDPRIM} executes)
  \item These values stay in effect until overwritten by another UDP
    (or a UDF or a UDC)
  \end{itemize}
\end{frame}


\begin{frame}
  \Frametitle{Building a NEW UDP/UDF by Example}

  \begin{itemize}
  \item {\tt ESP} ships with a directory named {\tt
    \$ESP\_HOME/contributions/UdpUdf}, which contains UDP/UDFs that
    are contributed by users
  \item {\tt UdpUdf} is pre-populated with several UDP/UDFs
    \begin{itemize}
    \item {\tt udpTemplate} --- a template from which most UDP/UDF
      development should start
      \begin{itemize}
      \item the description that follows starts here
      \end{itemize}
    \item {\tt udpTrain1} -- a full-featured UDP that contains:
      \begin{itemize}
      \item bottom-up and top-down builds
      \item makes a SolidBody, SheetBody, or WireBody
      \item has output arguments
      \item implements analytic sensitivities
      \end{itemize}
    \item {\tt udfTrain2} -- a full-featured UDF that contains:
      \begin{itemize}
      \item inputs from a file
      \item manipulation of attributes
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \Frametitle{Anatomy of directory {\tt udpTemplate}}

  \begin{itemize}
  \item {\tt template.hlp} --- file containing the text that will be
    included in the documentation in ESP's help facility
  \item {\tt template\_1.csm} --- file containing the first test case
  \item {\tt template\_1.png} --- screen dump when running {\tt
    template\_1.csm} (for help system)
  \item {\tt Makefile} --- file for compiling and linking the {\tt .c}
    file into the shared library (LINUX and MACOS)
  \item {\tt NMakefile} --- file for compiling and linking the {\tt .c}
    file into the shared library (Windows)
  \item {\tt template.c} --- file containing the implementation of the
    UDP/UDF
  \item {\tt verify\_7.8.1} --- a directory (folder) that contains data
    that is to be used during routine testing
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.hlp}}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=auto,xleftmargin=5mm]
UDPRIM template -
       purpose:
           serve as a template for creation of new UDPs
           as an example, it creates a sphere centered at the origin
       input Bodys:
           -none-
       input arguments (specified as name/value pairs):
           radius      radius of sphere                        [default 1]
       output arguments:
           -none-
       usage notes:
           the radius must be positive

           analytic sensitivities are not supported
       contributed by:
           John Dannenhoffer john@geocentrictech.com
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template\_1.csm}}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=auto,xleftmargin=5mm]
# template_1
# written by John Dannenhoffer

DESPMTR   RAD       2.0

UDPRIM    template  radius RAD

END
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Steps for Creating a UDP/UDF (1)}

  \begin{itemize}
  \item Make a new directory
    \begin{itemize}
    \item for example, create {\tt udpExercise1}
    \end{itemize}
  \item Copy all the files in {\tt udpTemplate} into your new folder
  \item Rename all files to your new UDP/UDF name
    \begin{itemize}
    \item for example
      \begin{itemize}
      \item rename {\tt template\_1.csm} to {\tt exercise1\_1.csm}
      \item rename {\tt template.c} to {\tt exercise1.c}
      \item rename {\tt template.hlp} to {\tt exercise1.hlp}
      \end{itemize}
    \end{itemize}
  \item Edit {\tt Makefile} by changing all occurances of {\tt
    template} to the name of your new UDP/UDF
  \item Edit {\tt NMakefile} by changing all occurances of {\tt
    template} to the name of your new UDP/UDF
  \item Remove the files from {\tt verify\_7.8.1}
    \begin{itemize}
    \item these will be automatically created below
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \Frametitle{Steps for Creating a UDP/UDF (2)}

  \begin{itemize}
  \item Modify the file that will provide help to the user
    \begin{itemize}
    \item for example, modify {\tt exercise1.hlp}
    \end{itemize}
  \item Modify the {\tt .csm} file(s) that will be used to verify that
    the UDP/UDF works as intended
    \begin{itemize}
    \item for example, modify {\tt exercise1\_1.csm}
    \item add other test files, naming them {\tt exercise1\_2.csm},
      \ldots
    \end{itemize}
  \item Modify the {\tt .c} file to implement your new UDP/UDF
    \begin{itemize}
    \item for example, modify {\tt exercise1.c}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \Frametitle{Steps for Creating a UDP/UDF (3)}

  \begin{itemize}
  \item Test that your UDP/UDF works as intended
    \begin{itemize}
    \item for example:
      \begin{itemize}
      \item run {\tt serveESP exercise1\_1} to verify that you get
        intended results
      \item run {\tt sensCSM -geom exercise1\_1} to verify that you get
        correct geometric sensitivities (which are returned as
        {\tt 1.0e-20} if finite-difference sensitivities are used)
      \item run {\tt sensCSM -tess exercise1\_1} to verify that you get
        correct tessellation sensitivities (which are returned as
        {\tt 1.0e-20} if finite-difference sensitivities are used)
      \end{itemize}
    \end{itemize}
  \item Build the verification data (to be used for automatic testing)
    \begin{itemize}
    \item for example:
      \begin{itemize}
      \item run {\tt serveESP -addVerify exercise1\_1}
      \item run {\tt sensCSM -geom -addVerify exercise1\_1}
      \item run {\tt sensCSM -tess -addVerify exercise1\_1}
      \end{itemize}
    \item this adds files to {\tt verify\_7.8.1}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (1)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=auto,xleftmargin=5mm]
/*
 ************************************************************************
 *                                                                      *
 * udpTemplate -- template UDP                                          *
 *                                                                      *
 *             this makes a sphere centered at the origin               *
 *                                                                      *
 *             Written by John Dannenhoffer @ Geocentric Technologies   *
 *                                                                      *
 ************************************************************************
 */

/*
 * Copyright (C) 2025  John F. Dannenhoffer, III (Geocentric Technologies))
 *
 * This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation; either
 *    version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *     MA  02110-1301  USA
 */

\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (1)}

  \begin{itemize}
  \item General notes:
    \begin{itemize}
    \item the header files {\tt udpUtilities.h} and {\tt
      udpUtilities.c} contain lots of code to hide the complexities of
      UDP/UDFs from the developer
    \item the order of the statements is generally important
    \item macros defined in these files are written in UPPERCASE
    \end{itemize}
  \item Lines 1--11: identifying comment
  \item Lines 13--30: copyright comment
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (2)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=last,xleftmargin=5mm]
/* uncomment the following to get DEBUG printouts */
//#define DEBUG 1

/* the number of "input" Bodys

   this only needs to be specified if this is a UDF (user-defined
   function) that consumes Bodys from OpenCSM's stack.  (the default
   value is 0).

   if NUMUDPINPUTBODYS>0  then exactly NUMUDPINPUTBODYS are in emodel
   if NUMUDPINPUTBODYS<0  then up to  -NUMUDPINPUTBODYS are in emodel
*/
#define NUMUDPINPUTBODYS 0

/* the number of arguments (specified below) */
#define NUMUDPARGS 1

/* set up the necessary structures (uses NUMUDPARGS) */
#include "udpUtilities.h"

/* shorthand macros for accessing argument values and velocities */
#define RADIUS(    IUDP)  ((double *) (udps[IUDP].arg[0].val))[0]
#define RADIUS_SIZ(IUDP)               udps[IUDP].arg[0].size

\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (2)}

  \begin{itemize}
  \item Line 33: uncomment the define to print DEBUG information
  \item Line 44: define the number of input Bodys
    \begin{itemize}
    \item set to 0 for a user-defined primitive (UDP)
    \end{itemize}
  \item Line 47: number of input and output arguments
  \item Line 50: this include file sets up transfers to and from
    {\tt ESP}
    \begin{itemize}
    \item this line MUST be in your UDP/UDF at this location
    \end{itemize}
  \item Lines 53--54: define macros to access input and output
    arguments
    \begin{itemize}
    \item these lines should be duplicated for every input/output
      argument
    \item the index in {\tt arg} should be incremented for each
      additional input/output argument
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (3)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=last,xleftmargin=5mm]
/* data about possible arguments
      argNames: argument name (must be all lower case)
      argTypes: argument type: +ATTRINT      integer input
                               -ATTRINT      integer output
                               +ATTRREAL     double input  (no sensitivities)
                               -ATTRREAL     double output (no sensitivities)
                               +ATTRREALSEN  double input  (with sensitivities)
                               -ATTRREALSEN  double output (with sensitivities)
                               +ATTRSTRING   string input
                               -ATTRSTRING   *** cannot be used ***
                               +ATTRFILE     input file
                               -ATTRFILE     *** cannot be used ***
                               +ATTRREBUILD  forces rebuild if any variable in
                                             semi-colon-separated list has been changed
                               -ATTRREBUILD  *** cannot be used ***
                               +ATTRRECYCLE  forces rebuild (always) by blocking recycling
                               -ATTRRECYCLE  *** cannot be used ***
      argIdefs: default value for ATTRINT
      argDdefs: default value for ATTRREAL or ATTRREALSEN */
static char  *argNames[NUMUDPARGS] = {"radius", };
static int    argTypes[NUMUDPARGS] = {ATTRREAL, };
static int    argIdefs[NUMUDPARGS] = {0,        };
static double argDdefs[NUMUDPARGS] = {1.,       };

/* get utility routines: udpErrorStr, udpInitialize, udpReset, udpSet,
                         udpGet, udpVel, udpClean, udpMesh */
#include "udpUtilities.c"
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (3)}

  \begin{itemize}
  \item Line 75: this lists the name of all input/output arguments
    \begin{itemize}
    \item only lowercase characters and digits can be used
    \end{itemize}
  \item Line 76: the type of each argument
    \begin{itemize}
    \item see lines 58--72 for available types
    \item in general, positive values used for input and negative
      values used for output
    \end{itemize}
  \item Line 77: the default values for all integer arguments
  \item Line 78: the default values for all real (double) arguments
  \item Line 82: definitions of the routines needed to interact with
    {\tt ESP}
    \begin{itemize}
    \item this line MUST be in your UDP/UDF at this location
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (4)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=last,xleftmargin=5mm]
/*
 ************************************************************************
 *                                                                      *
 *   udpExecute - execute the primitive                                 *
 *                                                                      *
 ************************************************************************
 */

int
udpExecute(ego  context,                /* (in)  EGADS context */
           ego  *ebody,                 /* (out) Body (or model) pointer */
           int  *nMesh,                 /* (out) number of associated meshes */
           char *string[])              /* (out) error message */
{
    int     status = EGADS_SUCCESS;

    double  data[18];
    char    *message=NULL;
    udp_T   *udps = *Udps;

    ROUTINE(udpExecute);

    /* --------------------------------------------------------------- */

#ifdef DEBUG
    /* debug printing of the input arguments */
    printf("udpExecute(context=%llx)\n", (long long)context);
    printf("radius(0) = %f\n", RADIUS(0));
#endif
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (4a)}

  \begin{itemize}
  \item Line 91: required so that {\tt ESP} can load this UDP/UDF
  \item Line 92: required name of the function that {\tt ESP} will
    call to execute this UDP/UDF
    \begin{itemize}
    \item if a UDP, the first argument ({\tt context}) is needed for
      many of the {\tt EGADS} routines
    \item if a UDF, the first argument will be {\tt emodel}, which is
      a {\tt EGADS} MODEL that contains the input Bodys
    \end{itemize}
  \item Line 93: a pointer to the Body (or MODEL) that is returned
    from this UDP/UDF to {\tt ESP}
  \item Line 94: {\tt nMesh} is currently not used
  \item Line 95: the error message returned from this UDP/UDF (might
    be blank)
  \end{itemize}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (4b)}

  \begin{itemize}
  \item Line 97: the default return status
  \item Line 99: data that is specific to this UDP/UDF
    \begin{itemize}
    \item in general, there will be many more variables defined here
    \end{itemize}
  \item Line 100: the declaration character string into which message
    will be written
    \begin{itemize}
    \item see below for macros used to allocate and free this
    \end{itemize}
  \item Line 101: a required line to have the UDP/UDF properly
    interact with {\tt ESP}
  \item Line 103: a required macro definition for reporting errors
    \begin{itemize}
    \item this should specify the name of the current function
    \end{itemize}
  \item Line 107--111: prints (if DEBUG was defined in line 33) the
    input arguments that were automatically set up
    \begin{itemize}
    \item the argument {\tt 0} refers to the current call
    \end{itemize}
  \end{itemize}
\end{frame}
    
\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (5)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=last,xleftmargin=5mm]
    /* default return values */
    *ebody  = NULL;
    *nMesh  = 0;
    *string = NULL;

    /* the place where messages to the user are placed */
    MALLOC(message, char, 100);
    message[0] = '\0';

    /* check arguments */
    if (RADIUS_SIZ(0) > 1) {
        snprintf(message, 100, "\"radius\" should be a scalar");
        status = OCSM_ILLEGAL_VALUE;
        goto cleanup;

    } else if (RADIUS(0) <= 0) {
        snprintf(message, 100, "\"radius\" should be a positive");
        status  = OCSM_ILLEGAL_VALUE;
        goto cleanup;

    }

    /* cache copy of arguments for future use */
    status = cacheUdp(NULL);
    CHECK_STATUS(cacheUdp);

#ifdef DEBUG
    /* debug printing of cached input arguments */
    printf("radius[%d] = %f\n", numUdp, RADIUS(numUdp));
#endif
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (5a)}

  \begin{itemize}
  \item Lines 113--115: default return values (if something goes wrong
    below)
  \item Line 118: invocation of the {\tt MALLOC} macro to allocate
    memory (in this case 100 characters)
    \begin{itemize}
    \item ensure that on line 100 the pointer was initialized to {\tt
      NULL}
    \end{itemize}
  \item Line 119: initialize {\tt message} to a zero-length string
  \item Lines 122--132: check the validity of the various input
    arguments
    \begin{itemize}
    \item error messages are written in {\tt message}
    \item {\tt status} is set to an appropriate error number (which
      should be negative)
      \begin{itemize}
      \item {\tt egadsErrors.h} defines standard error numbers for {\tt
        EGADS}
      \item {\tt OpenCSM.h} defined standard error numbers for {\tt
        OpenCSM}
      \end{itemize}
    \item control is transfered to {\tt cleanup} so that memory
      and other cleanup functions are executed
      \begin{itemize}
      \item do not use {\tt return}
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (5b)}

  \begin{itemize}
  \item Line 135: this call is required to cache the inputs so that
    the sensitvity routine can be applied correctly
  \item Line 136: a macro to check the return status
    \begin{itemize}
    \item if {\tt status} is negative, the error is reported and
      necessary cleanups are performed
    \end{itemize}
  \item Lines 138--141: more debug prints to show that the input
    arguments were cached properly
    \begin{itemize}
    \item an argument of {\tt 0} refers to the instance being created
    \item positive arguments indicate the instance number
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (6)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=last,xleftmargin=5mm]
    /* make SolidBody */
    data[0] = 0;
    data[1] = 0;
    data[2] = 0;
    data[3] = RADIUS(0);

    status = EG_makeSolidBody(context, SPHERE, data, ebody);
    CHECK_STATUS(EG_makeSolidBody);

    SPLINT_CHECK_FOR_NULL(*ebody);

    /* set the output value(s) */

    /* remember this model (Body) */
    udps[numUdp].ebody = *ebody;

}
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (6)}

  \begin{itemize}
  \item Lines 143--146: set up the array needed for {\tt
    EG\_makeSolidBody}
    \begin{itemize}
    \item see {\tt EGADS.pdf} (page 94) for a description of what
      there data are
    \end{itemize}
  \item Line 148: make the SPHERE SolidBody
  \item Line 149: same as line 136
  \item Line 151: the invocation of a macro to ensure that {\tt
    EG\_makeSolidBody} actually returned a Body
  \item Line 154: this UDP/UDF does not return any values
  \item Line 156: a required line to remember the Body that was made
    (so that the sensitivity routines work properly)
  \end{itemize}
\end{frame}
    
\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (7)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=last,xleftmargin=5mm]
cleanup:
#ifdef DEBUG
    printf("udpExecute -> numUdp=%d, *ebody=%llx\n", numUdp, (long long)(*ebody));
#endif

    if (strlen(message) > 0) {
        *string = message;
        printf("%s\n", message);
    } else if (status != EGADS_SUCCESS) {
        FREE(message);
        *string = udpErrorStr(status);
    } else {
        FREE(message);
    }

    return status;
}
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (7)}

  \begin{itemize}
  \item Line 159: the {\tt cleanup} label is REQUIRED for the macros
    to work properly
    \begin{itemize}
    \item this is where execution continues if an error is encountered
    \end{itemize}
  \item Lines 160--162: more DEBUG printing
  \item Lines 164--172: required code to properly return error
    messages to {\tt ESP}
    \begin{itemize}
    \item lines 168 and 171 show the {\tt FREE} macro, which has been
      set up to work with the {\tt MALLOC} macro
    \end{itemize}
  \item Line 174: the ONLY return statement from this function, which
    returns the error status back to {\tt ESP}
  \end{itemize}
\end{frame}
    
\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (8)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=last,xleftmargin=5mm]
/*
 ************************************************************************
 *                                                                      *
 *   udpSensitivity - return sensitivity derivatives for the "real" argument *
 *                                                                      *
 ************************************************************************
 */

int
udpSensitivity(ego    ebody,            /* (in)  Body pointer */
               int    npnt,             /* (in)  number of points */
               int    entType,          /* (in)  OCSM entity type */
               int    entIndex,         /* (in)  OCSM entity index (bias-1) */
               double uvs[],            /* (in)  parametric coordinates for evaluation */
               double vels[])           /* (out) velocities */
{
    int    status = EGADS_SUCCESS;

    int    iudp, judp;

    ROUTINE(udpSensitivity);

    /* --------------------------------------------------------------- */

#ifdef DEBUG
    if (uvs != NULL) {
        printf("udpSensitivity(ebody=%llx, npnt=%d, entType=%d, entIndex=%d, uvs=%f %f)\n",
               (long long)ebody, npnt, entType, entIndex, uvs[0], uvs[1]);
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (8)}

  \begin{itemize}
  \item For now, leave this code exactly as it is in {\tt template.c}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \Frametitle{Listing of {\tt template.c} (9)}

  \begin{minipage}{0.95\textwidth}
\begin{Verbatim}[frame=single,numbers=left,fontsize=\tiny,firstnumber=last,xleftmargin=5mm]
    } else {
        printf("udpSensitivity(ebody=%llx, npnt=%d, entType=%d, entIndex=%d, uvs=NULL)\n",
               (long long)ebody, npnt, entType, entIndex);
    }
#endif

    /* check that ebody matches one of the ebodys */
    iudp = 0;
    for (judp = 1; judp <= numUdp; judp++) {
        if (ebody == udps[judp].ebody) {
            iudp = judp;
            break;
        }
    }
    if (iudp <= 0) {
        status = EGADS_NOTMODEL;
        goto cleanup;
    }

    /* the following line should be included if sensitivities
       are not computed analytically */
    status = EGADS_NOLOAD;

cleanup:
#ifdef DEBUG
    printf("udpSensitivity -> vels=%f %f %f\n", vels[0], vels[1], vels[2]);
#endif
    return status;
}
\end{Verbatim}
  \end{minipage}
\end{frame}

\begin{frame}
  \Frametitle{Explanation of {\tt template.c} (8)}

  \begin{itemize}
  \item For now, leave this code exactly as it is in {\tt template.c}
  \end{itemize}
\end{frame}

\begin{frame}
  \Frametitle{Exercise1}

  \begin{itemize}
  \item Make a new UDP ({\tt exercise1}) in the directory (folder) {\tt
    udpExercise1}
    \begin{itemize}
    \item the purpose is to make a cylinder that is centered at the
      origin
    \item the input parameters are:
      \begin{itemize}
      \item {\tt length} - the length of the cylinder
      \item {\tt diam} - the diameter of the cylinder
      \item {\tt dirn} - a string containing the (single) character
        ``{\tt x}'', ``{\tt X}'', ``{\tt y}'', ``{\tt Y}'', ``{\tt
        z}'', or ``{\tt Z}'' to indicate that the cylinder's axis
        should be along the {\tt x-}, {\tt y-}, or {\tt z-} axis
      \end{itemize}
    \end{itemize}
  \item Make sure that your UDP does appropriate error checking
  \end{itemize}
\end{frame}

\end{document}
