.. _subroutines-programming:

***********
Programming
***********

Currently, user subroutines are only supported in FORTRAN 77. Any subroutine that can be compiled with a FORTRAN 77 compiler on the target execution machine can be used. The user should be aware that some computers support different FORTRAN language extensions than others. (In the future, other languages such as FORTRAN 90, C, and C++ may be supported.)

User subroutine variable types must interface directly with the matching variable types used in the main Sierra/SM code. Thus, the FORTRAN 77 subroutines should use only integer, double precision, or character types for any data used in the interface or in any query function. Using the wrong data type may yield unpredictable results. The methods used to pass character types from Sierra/SM to FORTRAN user subroutines can be machine-dependent, but generally this functionality works well.

The basic structure for the user subroutine is as follows:

.. code-block:: sierrainput

   subroutine sub_name(call list)
   {\{}declaration of variables{\}}
   {\{}retrieve parameters from Sierra/SM input file{\}}
   {\{}query Sierra/SM for information{\}}
   {\{}application-specific code     
      .
      .
   {\}}
   {\{}write computed values{\}}
   END

In general, the user will begin the subroutine with variable declarations. After the variable declarations, the user can then query the Sierra/SM input file for parameters. Additional Sierra/SM information such as field variables or element topology can then be retrieved from Sierra/SM. Once the user has collected all the information for the application, the application-specific portion of the code can be written. After the application-specific code is complete, the user may store computed values.

:numref:`use-intface` through :numref:`use-miscq` describe in detail the format for the interfaces to Sierra/SM that will allow the user to make the subroutine call, retrieve information from Sierra/SM, and write computed values. In these sections, mesh entities can be a node, an element face, or an element.

.. _use-intface:

Subroutine Interface
====================

The following interface is used for all user subroutines:

.. code-block:: sierrainput

   subroutine sub_name(int  num_objects,
                       int  num_values,
                       real evaluation_time,
                       int  object_ids[],
                       real output_values[],
                       int  output_flags[],
                       int  error_code) 

The name of the user subroutine, ``sub_name``, is selected by the user. Avoid names for the subroutine that are longer than 10 characters. This may cause build problems on some systems.

A detailed description of the input and output parameters is provided in Table :numref:`use-tab-subin` and Table :numref:`use-tab-subout`. 

.. _use-tab-subin:

.. csv-table:: Subroutine Input Parameters
   :align: center
   :delim: &
   :header: Input Parameter, Data Type, Parameter Description
   :widths: auto

   num_objects & Integer & Number of input mesh entities. For example, if the subroutine is a node set subroutine, this would be the number of nodes on which the subroutine will operate.
   num_values & Integer & Number of return values. This is the number of values per mesh entity.
   evaluation_time & Real & Time at which the subroutine should be evaluated. This may vary slightly from the current analysis time.  For example, in explicit dynamics analyses, velocities are evaluated one-half time step ahead.
   object_ids (num_objects) & Integer & Array of mesh-entity identification numbers. The array has a length of num_objects. The input numbers are the global numbers of the input objects. The object identification numbers can be used to query information about a mesh entity.

.. _use-tab-subout:

.. csv-table:: Subroutine Output Parameters
   :align: center
   :delim: &
   :header: Output Parameter, Data Type, Parameter Description
   :widths: auto

   output_values (num_values, num_objects) & Integer & Array of output values computed by the subroutine. The number of output values will be either the number of mesh entities or some multiple of the number of mesh entities. For example, if there were six nodes (num_objects equals 6) and one value was to be computed per node, the length of output_values would be 6. Similarly, if there were six nodes (num_objects equals 6) and three values were to be computed for each node (as for acceleration, which has X-, Y-, and Z-components), the length of output_values would be 18.
   output_flags (num_objects) & Integer & Array of returned flags for each set of data values. When used, this array will generally have a length of num_objects. The usage of the flags depends on subroutine type; the flags are currently used only for element death and for kinematic boundary conditions. For the kinematic boundary conditions (displacement, velocity, acceleration) a flag of --1 means ignore the constraint, a flag of 0 means set the absolute constraint value, and a flag of 1 means set the constraint with direction and distance.
   error_code & Integer & Error code returned by the user subroutine. A value of 0 indicates no errors. Any value other than zero is an error. If the return value is nonzero, Sierra/SM will report the error code and terminate the analysis.

.. _use-qfunc:

Query Functions
===============

Sierra/SM follows a design philosophy for user subroutines that a minimal amount of information should be passed through the call list. Additional information may be queried from within the subroutine. A user subroutine may query a wide variety of information from Sierra/SM.

.. _use-parq:

Parameter Query
---------------

A number of user subroutine parameters may be set as described in :numref:`use-param`. These subroutine parameters can be obtained from the Sierra/SM input file via the query functions listed below. 

.. code-block:: c

   aupst_get_real_param(string var_name, real var_value,  
                        int error_code)
  
   aupst_get_integer_param(string var_name, int var_value,  
                           int error_code)
  
   aupst_get_string_param(string var_name, string var_value,  
                          int error_code)

All three of these subroutine calls are tied to a corresponding  "parameter" command line that will appear in the Sierra/SM input file.  The  parameter command lines are described in :numref:`use-param`.  These command  lines are named based on the type of value they store, i.e., ``SUBROUTINE REAL PARAMETER``, ``SUBROUTINE INTEGER PARAMETER``, and ``SUBROUTINE STRING PARAMETER``.

We will use the example of a real parameter to show how the subroutine call works in conjunction with the ``SUBROUTINE REAL PARAMETER`` command line. Suppose we have a real parameter radius that is set to a value of 2.75 on the ``SUBROUTINE REAL PARAMETER`` command line:

.. code-block:: fortran

   SUBROUTINE REAL PARAMETER: radius = 2.75

Also suppose we have a call to ``aupst_get_real_parameter`` in the user subroutine: 

.. code-block:: fortran

   call aupst_get_real_parameter("radius",cyl_radius,error_code)

In the call to ``aupst_get_real_parameter``, we have ``var_name`` set to ``radius`` and ``var_value`` defined as the real FORTRAN variable ``cyl_radius``. The call to ``aupst_get_real_parameter`` will assign the value 2.75 to the FORTRAN variable ``cyl_radius``. A similar pattern is followed for integer and string parameters.

The arguments for the parameter-related query functions are described in Table :numref:`use-tab-greal`, Table :numref:`use-tab-gint`, and Table :numref:`use-tab-gstring`. The function is repeated before each table for quick reference.

.. code-block:: c

   aupst_get_real_param(string var_name, real var_value, int error_code)

.. _use-tab-greal:

.. csv-table:: aupst_get_real_param Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 15 15 15 55

   var_name & Input & String & Name of a real-valued subroutine parameter, as defined in the Sierra/SM input file via the ``SUBROUTINE REAL PARAMETER`` command line.
   var_value & Output & Real & Name of a real variable to be used in the FORTRAN subroutine. The FORTRAN variable var_value will be set to the value specified by the ``SUBROUTINE REAL PARAMETER`` command line.
   error_code & Output & Integer & Error code indicating status of retrieving the parameter value from the input file. If the retrieval is successful, error_code is set to 0. If the parameter is not found or is the wrong type, error_code is set to a value other than 0.

.. code-block:: c

   aupst_get_integer_param(string var_name, int var_value,  
                           int error_code)

.. _use-tab-gint:

.. csv-table:: aupst_get_integer_param Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 15 15 15 55

   var_name & Input & String & Name of an integer-valued subroutine parameter, as defined in the Sierra/SM input file via the ``SUBROUTINE INTEGER PARAMETER`` command line.
   var_value & Output & Integer & Name of an integer variable to be used in the FORTRAN subroutine. The FORTRAN variable var_value will be set to the value specified by the ``SUBROUTINE INTEGER PARAMETER`` command line.
   error_code & Output & Integer & Error code indicating status of retrieving the parameter value from the input file. If the retrieval is successful, error_code is set to 0. If the parameter is not found or is the wrong type, error_code is set to a value other than 0.

.. code-block:: c

   aupst_get_string_param(string var_name, string var_value,  
                          int error_code)

.. _use-tab-gstring:

.. csv-table:: aupst_get_string_param Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 15 15 15 55

   var_name & Input & String & Name of a string-valued subroutine parameter, as defined in the Sierra/SM input file via the ``SUBROUTINE STRING PARAMETER`` command line.
   var_value & Output & String & Name of a string variable to be used in the FORTRAN subroutine. The FORTRAN variable var_value will be set to the value specified by the ``SUBROUTINE STRING PARAMETER`` command line.
   error_code & Output & Integer & Error code indicating status of retrieving the parameter value from the input file. If the retrieval is successful, error_code is set to 0. If the parameter is not found or is the wrong type, error_code is set to a value other than 0.

.. _use-funcq:

Function Data Query
-------------------

The function data query routine listed below may be used for extracting data from a function that is defined in a ``FUNCTION`` command block in the Sierra/SM input file. This query allows the user to directly access information stored in a function defined in the Sierra/SM input file.

.. code-block:: c

   aupst_evaluate_function(string func_name, real input_times[], 
                           int num_times, real output_data[])

The arguments for this function are described in Table :numref:`use-tab-eval`.

.. _use-tab-eval:

.. csv-table:: aupst_evaluate_function Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: auto

   func_name & Input & String & Name of the function to look up.
   input_times(num_times) & Input & Real & Array of times used to extract values of the function.
   num_times & Input & Integer & Length of the array input_times.
   output_data(num_times) & Output & Real & Array of output values of the named function at the specified times.

.. _use-timeq:

Time Query
----------

The time query function can be used to determine the current analysis time. This is the time associated with the new time step. This time may not be equivalent to the ``evaluation_time`` argument passed into the subroutine (see :numref:`use-intface`, Table :numref:`use-tab-subin`) as some boundary conditions need to be evaluated at different times than others. The parameter of the time query function listed below is given in Table :numref:`use-tab-time`.

.. code-block:: c

   aupst_get_time(real time)

.. _use-tab-time:

.. csv-table:: aupst_get_time Argument
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: auto

   time & Output & Real & Current analysis time.

.. _use-fieldq:

Field Variables
---------------

Field variables (displacements, stresses, etc.) may be defined on groups of mesh entities. Many queries are available for getting and putting field variables. These queries involve passing in a set of mesh-entity identification numbers to receive field values on the mesh entities. There are query functions to check for the existence and size of a field, functions to retrieve the field values, and functions to store new variables in a field. The field query functions listed below can be used to extract any nodal or element variable field. 

.. code-block:: c

   aupst_check_node_var(int num_nodes, int num_components,
                        int node_ids[], string var_name,
                        int error_code)
   
   aupst_check_elem_var(int num_elems, int num_components,
                        int elem_ids[], string var_name,
                        int error_code)
   
   aupst_get_node_var(int num_nodes, int num_components,
                      int node_ids[], real return_data[],
                      string var_name, int error_code)
   
   aupst_get_elem_var(int num_elems, int num_components,
                      int elem_ids[], real return_data[],
                      string var_name, int error_code)
   
   aupst_get_elem_var_offset(int num_elems, int num_components,
                             int offset, int elem_ids[],
                             real return_data[], string var_name,
                             int error_code)
   
   aupst_put_node_var(int num_nodes, int num_components,
                      int node_ids[], real new_data[],
                      string var_name, int error_code)
   
   aupst_put_elem_var(int num_elems, int num_components,
                      int elem_ids[], real new_data[],
                      string var_name, int error_code)
   
   aupst_put_elem_var_offset(int num_elems, int num_components,
                             int offset, int elem_ids[],
                             real new_data[], string var_name,
                             int error_code)

The arrays where data are stored are static arrays. These arrays of a set size will be declared at the beginning of a user subroutine. The query functions to check for the existence and size of a field can be used to ensure that the size of the array of information being returned from Sierra/SM does not exceed the size of the array allocated by the user.

The arguments to field query functions are defined in Table :numref:`use-tab-chnode` through Table :numref:`use-tab-puteloff`. The function is repeated before each table for quick reference.

The ``var_name`` strings may be the name of any variable that could be used for code output and additionally may include the component syntax described in :numref:`output-syntax`.

.. code-block:: c

   aupst_check_node_var(int num_nodes, int num_components,
                        int node_ids[], string var_name,
                        int error_code)

.. _use-tab-chnode:

.. csv-table:: aupst_check_node_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_nodes & Input & Integer & Number of nodes used to extract field information.
   num_components & Output & Integer & Number of components in the field information. A displacement field at a node has three components, for example.
   node_ids (num_nodes) & Input & Integer & Array of size num_nodes listing the node identification number for each node where field information will be retrieved.
   var_name & Input & String & Name of the field variable. The field variable must be a defined Sierra/SM variable.
   error_code & Output & Integer & Error code indicating status of retrieving the field. If the retrieval is successful, error_code is set to 0. If a nonzero value is returned for error_code, the field variab ledoes not exist or is not defined on one or more of the input nodes.

.. code-block:: c

   aupst_check_elem_var(int num_elems, int num_components,
                        int elem_ids[], string var_name,
                        int error_code)

.. _use-tab-chel:

.. csv-table:: aupst_check_elem_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_elems & Input & Integer & Number of elements used to extract field information.
   num_components & Output & Integer & Number of components in the field information. A stress field for an eight-node hexahedron element has six components, for example.
   elem_ids (num_elems) & Input & Integer & Array of size num_elems listing the element identification number for each element where field information will be retrieved.
   var_name & Input & String & Name of the field variable. The field variable must be a defined Sierra/SM variable.
   error_code & Output & Integer & Error code indicating status of retrieving the field. If the retrieval is successful, error_code is set to 0. If a nonzero value is returned for error_code, the field variab ledoes not exist or is not defined on one or more of the input nodes.

.. code-block:: c

   aupst_get_node_var(int num_nodes, int num_components,
                      int node_ids[], real return_data[],
                      string var_name, int error_code)

.. _use-tab-getnode:

.. csv-table:: aupst_get_node_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_nodes & Input & Integer & Number of nodes used to extract field information.
   num_components & Input & Integer & Number of components in the field information. A displacement field at a node has three components, for example.
   node_ids (num_nodes) & Input & Integer & Array of size num_nodes listing the node identification number for each node where field information will be retrieved.
   return_data (num_components, num_nodes) & Output & Real & Array of size num_components :math:`\times` num_nodes containing the field data at each node.
   var_name & Input & String & Name of the field variable. The field variable must be a defined Sierra/SM variable.
   error_code & Output & Integer & Error code indicating status of retrieving the field. If the retrieval is successful, error_code is set to 0. If a nonzero value is returned for error_code, the field variab ledoes not exist or is not defined on one or more of the input nodes.

.. code-block:: c

   aupst_get_elem_var(int num_elems, int num_components,
                      int elem_ids[], real return_data[],
                      string var_name, int error_code)

.. _use-tab-getel:

.. csv-table:: aupst_get_elem_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: auto

   num_elems & Input & Integer & Number of elements used to extract field information.
   num_components & Input & Integer & Number of components in the field information. A stress field for an eight-node hexahedron element has six components, for example.
   elem_ids (num_elems) & Input & Integer & Array of size num_elems listing the element identification number for each element where field information will be retrieved.
   return_data (num_components, num_elems) & Output & Real & Array of size num_components :math:`\times` num_elems containing the field data for each element.
   var_name & Input & String & Name of the field variable. The field variable must be a defined Sierra/SM variable.
   error_code & Output & Integer & Error code indicating status of retrieving the field. If the retrieval is successful, error_code is set to 0. If a nonzero value is returned for error_code, the field variable does not exist or is not defined on one or more of the input nodes.

.. code-block:: c

   aupst_get_elem_var_offset(int num_elems, int num_components,
                             int offset, int elem_ids[],
                             real return_data[], string var_name,
                             int error_code)

.. _use-tab-geteloff:

.. csv-table:: aupst_get_elem_var_offset Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: auto

   num_elems & Input & Integer & Number of elements used to extract field information.
   num_components & Input & Integer & Number of components in the field information. A stress field for an eight-node hexahedron element has six components, for example.
   offset & Input & Integer & Offset into var_name field variable at which to get data.
   elem_ids (num_elems) & Input & Integer & Array of size num_elems listing the element identification number for each element where field information will be retrieved.
   return_data (num_components, num_elems) & Output & Real & Array of size num_components :math:`\times` num_elems containing the field data for each element.
   var_name & Input & String & Name of the field variable. The field variable must be a defined Sierra/SM variable.
   error_code & Output & Integer & Error code indicating status of retrieving the field. If the retrieval is successful, error_code is set to 0. If a nonzero value is returned for error_code, the field variable does not exist or is not defined on one or more of the input nodes.

.. code-block:: c

   aupst_put_node_var(int num_nodes, int num_components,
                      int node_ids[], real new_data[],
                      string var_name, int error_code)

.. _use-tab-putnode:

.. csv-table:: aupst_put_node_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: auto

   num_nodes & Input & Integer & Number of nodes for which the user will specify the field data.
   num_components & Input & Integer & Number of components in the field information. A displacement field at a node has three components, for example.
   node_ids (num_nodes) & Input & Integer & Array of size num_nodes listing the node identification number for each node where field information will be retrieved.
   new_data (num_components, num_nodes) & Input & Real & Array of size num_components :math:`\times` num_nodes containing the new data for the field.
   var_name & Input & String & Name of the field variable. The field variable must be a defined Sierra/SM variable.
   error_code & Output & Integer & Error code indicating status of retrieving the field. If the retrieval is successful, error_code is set to 0. If a nonzero value is returned for error_code, the field variable does not exist or is not defined on one or more of the input nodes.

.. code-block:: c

   aupst_put_elem_var(int num_elems, int num_components,
                      int elem_ids[], real new_data[],
                      string var_name, int error_code)

.. _use-tab-putel:

.. csv-table:: aupst_put_elem_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_elems & Input & Integer & Number of elements for which the user will specify the field data.
   num_components & Input & Integer & Number of components in the field information. A stress field for an eight-node hexahedron element has six components, for example.
   elem_ids(num_elems) & Input & Integer & Array of size num_elems listing the element identification number for each element where field information will be retrieved.
   new_data(num_components, num_elems) & Input & Real & Array of size num_components :math:`\times` num_elems containing the new data for the field.
   var_name & Input & String & Name of the field variable. The field variable must be a defined Sierra/SM variable.
   error_code & Output & Integer & Error code indicating status of retrieving the field. If the retrieval is successful, error_code is set to 0. If a nonzero value is returned for error_code, the field variable does not exist or is not defined on one or more of the input nodes.

.. code-block:: c

   aupst_put_elem_var_offset(int num_elems, int num_components,
                             int offset, int elem_ids[],
                             real new_data[], string var_name,
                             int error_code)

.. _use-tab-puteloff:

.. csv-table:: aupst_put_elem_var_offset Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_elems & Input & Integer & Number of elements for which the user will specify the field data.
   num_components & Input & Integer & Number of components in the field information. A stress field for an eight-node hexahedron element has six components, for example.
   offse t&Input & Integer & Offset into var_name field variable at which to put data.
   elem_ids(num_elems) & Input & Integer & Array of size num_elems listing the element identification number for each element where field information will be retrieved.
   new_data(num_components, num_elems) & Input & Real & Array of size num_components :math:`\times` num_elems containing the new data for the field.
   var_name & Input & String & Name of the field variable. The field variable must be a defined Sierra/SM variable.
   error_code & Output & Integer & Error code indicating status of retrieving the field. If the retrieval is successful, error_code is set to 0. If a nonzero value is returned for error_code, the field variable does not exist or is not defined on one or more of the input nodes.

.. _use-globalq:

Global Variables
----------------

Global variables may be extracted or set from user subroutines.  A global variable has a single value for a given region.  Global variables have limited support for parallel operations.  The subroutine ``aupst_put_global_var`` attempts to immediately modify and optionally perform a parallel reduction on the value of a global variable.  ``aupst_put_global_var`` can specify the variable reduction type "sum", "min", "max", and "none."  If the "none" option is passed to the routine no global reduction operation will take place, only the processor local copy of the global variable will be modified.  If any option other than "none" is used care must be taken to call ``aupst_put_global_var`` on all processors at the same time with the same arguments.  Failure to call the routine from all processors will result in the code hanging.  For some types of subroutines this is not possible or reliable.  For example, a boundary condition subroutine may not be called at all on a processor that contains no nodes in the set of nodes assigned to the boundary condition.  It is recommended that the ``aupst_put_global_var`` function only be used in conjunction with a user subroutine referenced in a ``USER OUTPUT`` command block (:numref:`output-results-user`).

Only user-defined global variables may be modified by the user subroutine (see :numref:`subroutines-file-variables`). However, any global variable that exists on the region may be checked or extracted. The following subroutine calls pertain to global variables:

.. code-block:: c

   aupst_check_global_var(int num_comp, string var_name
                          int error_code)
   
   aupst_get_global_var(int num_comp, real return_data,
                        string var_name, int error_code)
   
   aupst_put_global_var(int num_comp, real input_data,
                        string var_name, 
                        string reduction_type,
                        int error_code)

The arguments for subroutine calls pertaining to global variables are defined in Table :numref:`use-tab-chglo` through Table :numref:`use-tab-putglo`. The call is repeated before each table for quick reference.

.. code-block:: c

   aupst_check_global_var(int num_comp, string var_name
                          int error_code)

.. _use-tab-chglo:

.. csv-table:: aupst_check_global_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_comp & Output & Integer & Number of components of the global variable.
   var_name & Input & String & Name of the global variable.
   error_code & Output & Integer & Error code indicating status of accessing the global variable. If there is no error in accessing this variable, error_code is set to 0. A nonzero value of error_code means theglobal variable does not exist or in some way cannot be accessed.

.. code-block:: c

   aupst_get_global_var(int num_comp, real return_data,
                        string var_name, int error_code)

.. _use-tab-getglo:

.. csv-table:: aupst_get_global_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_comp & Input & Integer & Number of components of the global variable.
   return_data & Output & Real & Value of the global variable.
   var_name & Input & String & Name of the global variable.
   error_code & Output & Integer & Error code indicating status of accessing the global variable. If there is no error in accessing this variable, error_code is set to 0. A nonzero value of error_code means the global variable does not exist or in some way cannot be accessed.

.. code-block:: c

   aupst_put_global_var(int num_comp, real input_data,
                        string var_name, 
                        string reduction_type,
                        int error_code)

.. _use-tab-putglo:

.. csv-table:: aupst_put_global_var Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: auto

   num_comp & Input & Integer & Number of components of the global variable.
   input_data & Input & Real & New value of the global variable.
   var_name & Input & String & Name of the global variable.
   reduction_type & Input & String & Type of parallel reduction to perform on the variable. Options are "sum", "min", "max", and "none." 
   error_code & Output & Integer & Error code indicating status of accessing the global variable. If there is no error in accessing this variable, error_code is set to 0. A nonzero value of error_code means the global variable does not exist, in some way cannot be accessed, or may not be overwritten.

.. _use-topoq:

Topology Extraction
-------------------

The element and surface subroutines operate on groups of elements or faces. The elements and faces may have a variety of topologies. Topology queries can be used to get topological data about elements and faces. The topology of an object is represented by an integer. The integer is formed from a function of the number of dimensions, vertices, and nodes of an object. The topology of an object is given by:

.. code-block:: sierrainput

  topology = num_node + 100 * num_vert + 10000 * num_dim

In a FORTRAN routine, the number of nodes can easily be extracted with the mod function:

.. code-block:: fortran

   num_node = mod(topo,100)
   num_vert = mod(topo / 100, 100)
   num_dim  = mod(topo / 10000, 100)

Table :numref:`use-tab-tops` lists the topologies currently in use by Sierra/SM.

.. _use-tab-tops:

.. csv-table:: Topologies Used by Sierra/SM
   :align: center
   :delim: &
   :header: Topology, Element / Face Type
   :widths: auto

   00101 & One-node particle
   10202 & Two-node beam, truss, or damper
   20404 & Four-node quadrilateral
   20303 & Three-node triangle
   20304 & Four-node triangle
   20306 & Six-node triangle
   30404 & Four-node tetrahedron
   30410 & Ten-node tetrahedron
   30808 & Eight-node hexahedron
   30606 & Six-node wedge
   30505 & Five-node pyramid

The following topology query functions are available in Sierra/SM:

.. code-block:: c

   aupst_get_elem_topology(int num_elems, int elem_ids[],
                           int topology[], int error_code)
  
   aupst_get_elem_nodes(int num_elems, int elem_ids[],
                        int elem_node_ids[], int error_code)
  
   aupst_get_face_topology(int num_faces, int face_ids[],
                           int topology[], int error_code)
  
   aupst_get_face_nodes(int num_faces, int face_ids[],
                        int face_node_ids[], int error_code)

The arguments for the topology extraction functions are defined in Table :numref:`use-tab-geteltop`  through Table :numref:`use-tab-getfacenode`. The function is repeated before each table for quick reference.

.. code-block:: c

   aupst_get_elem_topology(int num_elems, int elem_ids[],
                           int topology[], int error_code)

.. _use-tab-geteltop:

.. csv-table:: aupst_get_elem_topology Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_elems & Input & Integer & Number of elements from which the topology will be extracted.
   elem_ids(num_elems) & Input & Integer & Array of length num_elems listing the element identification for each element from which the topology will be extracted.
   topology(num_elems) & Output & Integer & Array of length num_elems that has the topology for each element. See Table 8.18.
   error_code & Output & Integer & Error code indicating status of retrieving the element identification numbers. If the retrieval is successful, error_code is set to 0. A nonzero value is returned for error_code if one of the element identification numbers is not valid.

.. code-block:: c

   aupst_get_elem_nodes(int num_elems, int elem_ids[],
                        int elem_node_ids[], int error_code)

.. _use-tab-getelnode:

.. csv-table:: aupst_get_elem_nodes Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_elems & Input & Integer & Number of elements from which the topology will be extracted.
   elem_ids(num_elems) & Input & Integer & Array of length num_elems listing the element identification for each element from which the topology will be extracted.
   elem_node_ids(number of nodes for element type :math:`\times` num_elems) & Output & Integer & Array containing the node identification numbers for each element requested. The length of the array is the total number of nodes contained in all elements. If the elements are eight-node hexahedra, then the number of nodes will be 8 :math:`\times` num_elems. The first set of eight entries in the array will be the eight nodes defining the first element. The second set of eight entries will be the eight nodes defining the second element, and so on.
   error_code & Output & Integer & Error code indicating status of retrieving the element identification numbers. If the retrieval is successful, error_code is set to 0. A nonzero value is returned for error_code if one of the element identification numbers is not valid.

.. code-block:: c

   aupst_get_face_topology(int num_faces, int face_ids[],
                           int topology[], int error_code)

.. _use-tab-getfacetop:

.. csv-table:: aupst_get_face_topology Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_faces & Input & Integer & Number of faces from which the topology will be extracted.
   face_ids(num_faces) & Input & Integer & Array of length num_faces listing the face identification for each face from which the topology will be extracted.
   topology(num_faces) & Output & Integer & Array of length num_faces containing the output topologies of each face.
   error_code & Output & Integer & Error code indicating status of retrieving the face identification numbers. If the retrieval is successful, error_code is set to 0. A nonzero value is returned for error_code if one of the face identification numbers is not valid.

.. code-block:: c

   aupst_get_face_nodes(int num_faces, int face_ids[],
                        int face_node_ids[], int error_code)

.. _use-tab-getfacenode:

.. csv-table:: aupst_get_face_nodes Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_faces & Input & Integer & Number of faces from which the topology will be extracted.
   face_ids(num_faces) & Input & Integer & Array of length num_faces listing the face identification for each face from which the topology will be extracted.
   face_node_ids(number of nodes for face type :math:`\times` num_faces) & Output & Integer & Array containing the node identification numbers for each face requested. The length of the array is the total number of nodes contained in all faces. If the faces are four-node quadrilaterals, then the number of nodes will be 4 :math:`\times` num_faces. The first set of four entries in the array will be the four nodes defining the first face. The second set of four entries will be the four nodes defining the second face, and so on.
   error_code & Output & Integer & Error code indicating status of retrieving the face identification numbers. If the retrieval is successful, error_code is set to 0. A nonzero value is returned for error_code if one of the face identification numbers is not valid.

.. _use-miscq:

Miscellaneous Query Functions
=============================

Many miscellaneous query functions are available for computing some commonly used quantities.

.. code-block:: c

   aupst_get_elem_centroid(int num_elems, int elem_ids[],
                           real centroids, int error_code)
  
   aupst_get_point(string point_name, real point_coords,
                   int error_code)
  
   aupst_get_proc_num(proc_num)

The arguments for the miscellaneous query functions are defined in Table :numref:`use-tab-getoneel`  through Table :numref:`use-tab-getprocnum`. The function is repeated before each table for quick reference.

.. code-block:: c

   aupst_get_elem_centroid(int num_elems, int elem_ids[],
                           real centroids[], int error_code)

.. _use-tab-getoneel:

.. csv-table:: aupst_get_elem_centroid Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   num_elems & Input & Integer & Number of elements for which to extract the topology.
   elem_ids(num_elems) & Input & Integer & Array of length num_elems listing the element identification for each element for which the centroid will be computed.
   centroids(3, num_elems) & Output & Real & Array of length 3 :math:`\times` num_elems containing the centroid of each element.
   error_code & Output & Integer & Error code indicating status of retrieving the element identification numbers. If the retrieval is successful, error_code is set to 0. A nonzero value is returned for error_code if one of the element identification numbers is not valid.

.. code-block:: c

   aupst_get_point(string point_name, real point_coords,
                   int error_code)

.. _use-tab-getpoint:

.. csv-table:: aupst_get_point Arguments
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   point_name & Input & String & SIERRA name for a given point.
   point_coords(3) & Output & Real & Array of length 3 containing the :math:`x`, :math:`y`, and :math:`z` coordinates of the point.
   error_code & Output & Integer & Error code indicating status of retrieving the point. If the retrieval is successful, error_code is set to 0. A nonzero value is returned for error_code if the point cannot be found

.. code-block:: c

   aupst_get_proc_num(proc_num)

.. _use-tab-getprocnum:

.. csv-table:: aupst_get_proc_num Argument
   :align: center
   :delim: &
   :header: Parameter, Usage, Data Type, Description
   :widths: 20 15 15 50

   proc_num & Output & Integer & Processor number of the calling process. This number can be used for informational purposes. A common example is that output could only be written by a single processor, e.g., processor 0, rather than by all processors.
