\section{The GANLIB Version 5 architecture}

The GANLIB is a small library that is linked to a software application in order to facilitate modularity,
interoperability, and to bring generic capabilities in term of  data transfer. The GANLIB is an application programming
interface (API) made of subroutines that are called by the software application (e.g., a lattice code) or by
the multi-physics surrounding application. In other words, the GANLIB acts as a standardized interface between the
software application and the multi-physics application, as depicted in \Fig{multi}.

\begin{figure}[htbp]
\begin{center} 
\epsfxsize=9cm
\centerline{ \epsffile{multiphysics.eps}}
\parbox{12cm}{\caption{Implementing a multi-physics application.}\label{fig:multi}}
\end{center}  
\end{figure}
\goodbreak

\vskip 0.08cm

The GANLIB is made of two distinct and inter-related components:
\begin{itemize}
\item CLE--2000 is a compact supervisor responsible for the free-format recovery of input data, for the modularization
of the software application and for the insertion of loops and control statements in the input data flow. CLE-2000
permits the conception of {\sl computational schemes}, dedicated to specific engineering studies, without any need
for recompilation of the software application.\cite{cle2000}
\item LCM objects are data structures used to transfer data between modules of the software application and towards the 
multi-physics application. LCM objects are structures made of {\sl associative table} and {\sl heterogeneous lists}. These
structures are either {\sl memory resident} or {\sl persistent} (i.e., stored in a file). The LCM object API is implemented
with access efficiency as its first requirement, even for frequent calls with small chunks of data.\cite{lcm2002}
\end{itemize}

\vskip 0.08cm

The GANLIB Version 5 is implemented in the ANSI~C programming language\cite{ansiC}, in order to maximize its compatibility
in a multi-physics environment where different components are implemented in various programming languages (C++,
Fortran, Java, etc.). The GANLIB Version 5 is {\sl 64-bit clean}, another benefit of using an ANSI~C implementation. This
last property allows the execution of software applications with 32-bit integers and 64-bit addresses. Specific Fortran
APIs are also available and are implemented according to the C interoperability mechanism,
available in Fortran~2003 and standardized by the International Organization for Standardization (ISO). This architecture is 64-bit clean.\cite{fortran2003}

\subsection {From Versions 3 or 4 to Version 5}

The Version 3 and Version 4 software applications available at GAN are using a legacy GANLIB, implemented in FORTRAN~77,
and relatively unchanged for more than 15~years.\cite{lcm1994} The only addition in Version~4 are the heterogeneous lists within LCM
objects. This Fortran implementation is {\sl not} ISO standard and {\sl not} 64-bit clean. However, the corresponding API
is mature and efficient, two qualities that we want to preserve.

\vskip 0.08cm

A software application is not 64-bit clean when 32-bit integers are used to store addresses (or differences between
two addresses). This nasty operation is possible in ANSI~C but can always be avoided. Unfortunately, this operation
is extensively used in software applications DRAGON, TRIVAC and DONJON Versions 3 or 4, due to design constraints
related to the choice of FORTRAN~77 as programming language.

\vskip 0.08cm

Versions 3 or 4 software applications can be re-implemented around the Version~5 GANLIB in order to become ISO standard and 64-bit clean.
However, the conversion process is not automatic and is time-consuming. Two major modifications must be done:
\begin{enumerate}
\item All variables containing addresses of LCM objects must be declared as {\tt TYPE(C\_PTR)} instead of been
declared as {\tt INTEGER}. The intrinsic type {\tt TYPE(C\_PTR)} is available in Fortran~2003, as defined by ISO.
\item Every call to the {\tt SETARA} subroutine of the GANLIB must be replaced by an {\tt ALLOCATE} statement and every call to the {\tt RLSARA}
subroutine must be replaced by a {\tt DEALLOCATE} statement. Statements {\tt ALLOCATE}  and {\tt DEALLOCATE} are
available in Fortran~90, as defined by ISO. The {\tt ALLOCATABLE} attribute is used to identify allocated arrays. Blank common
are no longer required as reference addresses. This modification
is the more time-consuming of the two.
\end{enumerate}

\vskip 0.08cm

Implementing software applications in Fortran 2003 offers the opportunity to use advanced features of this language, such
as pointers, Fortran modules (not to be confused with CLE-2000 modules) and polymorphism. However, this is a programming
style issue which is independent of the selection of GANLIB Version 5. It is possible, as a pragmatic choice, to keep the Fortran-77 programming style
and just use the GANLIB Version~5, {\tt TYPE(C\_PTR)} types and {\tt ALLOCATABLE} arrays.

\section {The ANSI C {\sc lcm} API}\label{sect:lcmapiC}

LCM objects are data structures, implemented in ANSI~C, with characteristics of {\sl associative tables} (a.k.a., dictionaries or
hash tables) and/or {\sl heterogeneous lists} (a.k.a., cell arrays). These data structures are either stored in memory or are persistent
(i.e., stored in a file). These objects are primarily accessed via an API implemented in ANSI~C. Access by other languages is
possible via {\sl specific bindings} that are also described in this report. Deep copy and serialization utilities are available.

\vskip 0.08cm

Persistence is implemented using XSM data structures, together with another API implemented in ANSI~C. {\sc xsm} files are used
in this case. However, the XSM API
is invoked from within LCM and a developer using the GANLIB never has to call it directly.

\vskip 0.08cm

The {\sc lcm} API was implemented in such a way that
\begin{itemize}
\item the access from ANSI~C or from Fortran is highly optimized, even for frequent calls with small chunks of data.
\item the access from other languages (Matlab, Python, Java, or Objective~C) permits a complete read/write access
of the totality of information contained in the object.
\end{itemize}

\vskip 0.08cm

This technical report contains the precise description of each ANSI~C function available in the {\sc lcm} API and dedicated
to a programmer using the GANLIB Version~5.

\vskip 0.08cm

A LCM object is a collection of the following elements:
\vskip 0.08cm
{\bf Associative tables}  \\
An associative table is equivalent to a Python dictionary or to a Java hash table. Each element of an associative table is an association between a 12-character name and a block of data. A block of data can be an array of some elementary type, another associative table or an heterogeneous list. Tree structures can be constructed that way.
\vskip 0.08cm
{\bf Heterogeneous list}  \\
An heterogeneous list is an ordered set of blocks of information (referred as ``0", ``1", ``2", etc. ). A block of data can be an array of some elementary type, another associative table or an heterogeneous list.
\vskip 0.08cm
{\bf Array of elementary type}  \\
An array of elementary type is a set of consecutive values in memory, all of the same type. The type is selected in the following table: \\
\begin{tabular}{|c|c|c|}
\hline
index & array of ... & type\\
\hline
1 & 32-bit integer & int\_32 \\
2 & 32-bit real & float\_32 \\
3 & 4-character strings &  \\
4 & 64-bit real & double\_64 \\
5 & 32-bit logical & int\_32 \\
6 & 64-bit complex&   \\
\hline
\end{tabular}

\vskip 0.08cm

Any ANSI~C function calling the {\sc lcm} API must use an include file of the form
\begin{verbatim}
#include "lcm.h"
\end{verbatim}

Each LCM object has a {\sl root associative table} from which the complete object is constructed.

\clearpage

\subsection{General utility functions}

\subsubsection{strcut\_c\index{strcut\_c}}

Copy {\tt n} characters from string {\tt ct} to {\tt s}. Eliminate leading {\tt ' '} and {\tt '}$\backslash${\tt 0'}
characters in {\tt s}. Terminate {\tt s} with a {\tt '}$\backslash${\tt 0'}.

\begin{verbatim}

strcut_c(s, ct, n);
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ct} & {\it char*} & character variable of length {\tt n}. May not be null-terminated.\\
\hline
{\tt n} & {\it int\_32} & length of {\tt ct}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt s} & {\it char*} & null terminated string. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{strfil\_c\index{strfil\_c}}

Copy {\tt n} characters from string {\tt ct} to {\tt s}. Eliminate {\tt '}$\backslash${\tt 0'} characters and
pack with {\tt ' '}. Assume that {\tt ct} is null-terminated.

\begin{verbatim}

strfil_c(s, ct, n);
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ct} & {\it char*} & null-terminated character variable.\\
\hline
{\tt n} & {\it int\_32} & expected length of {\tt s}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt s} & {\it char*} & character variable of length {\tt n} (not null-terminated). \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsection{Opening, closing and validation of LCM objects}

\subsubsection{lcmop\_c\index{lcmop\_c}}

Open an LCM object (either memory resident or persistent). Obtain the address of the LCM
object if it is created. Note that CLE-2000 is responsible to perform the calls to
{\tt lcmop\_c} for the LCM objects that are used as parameters of a CLE-2000 module. The use
of {\tt lcmop\_c} is generally restricted to the use of temporary LCM objects created within a CLE-2000 module.

\begin{verbatim}

lcmop_c(iplist,namp,imp,medium,impx);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the LCM object if {\tt imp=1} or {\tt imp=2}. {\tt iplist} corresponds to the address of the root associative table. \\
\hline
{\tt namp} & {\it char[73]} & name of the LCM object if {\tt imp=0}. \\
\hline
{\tt imp} & {\it int\_32} & =0 to create a new LCM object ; 
                                  =1 to modify an existing LCM object; 
				  =2 to access an existing LCM object in {\bf read-only} mode. \\
\hline
{\tt medium} & {\it int\_32} & =1 to use a memory-resident LCM object; 
                                     =2 to use an {\sc xsm} file to store the LCM object. \\
\hline
{\tt impx} & {\it int\_32} & print parameter. Equal to zero to suppress all printings. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of an LCM object if {\tt imp=0}. \\
\hline
{\tt namp} & {\it char*} & name of the LCM object if {\tt imp=1} or {\tt imp=2}. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmcl\_c\index{lcmcl\_c}}

Close an LCM object (either memory resident or persistent). Note that CLE-2000 is responsible to perform the calls to
{\tt lcmcl\_c} for the LCM objects that are used as parameters of a CLE-2000 module. The use
of {\tt lcmcl\_c} is generally restricted to the use of temporary LCM objects created within a CLE-2000 module.

\vskip 0.2cm

A LCM object can only be closed if {\tt iplist} points towards its root directory.

\begin{verbatim}

lcmcl_c(iplist,iact);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the LCM object (address of the root directory of the LCM object). \\
\hline
{\tt iact} & {\it int\_32} & =1 close the LCM object without destroying it; =2 and destroying it \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & {\tt iplist=null} indicates that the LCM object is closed and destroyed. A memory-resident LCM object keeps the
same address during its complete existence. A persistent LCM object is associated to an XSM file and is represented by a different
value of {\tt iplist} each time it is reopened. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmval\_c\index{lcmval\_c}}

Function to validate a single block of data in a LCM object or the totality of the LCM object,
starting from the address of an associative table. This function has no effect if the object is
persistent. The validation consists to verify the connections between the elements of the LCM
object, to verify that each element of the object is defined and to check for possible memory corruptions.
If an error is detected, the following message is issued:

\begin{verbatim}
LCMVAL_C: BLOCK xxx OF THE TABLE yyy HAS BEEN OVERWRITTEN.
\end{verbatim}

This function is called as

\begin{verbatim}

lcmval_c(iplist,namp);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table or of the heterogeneous list. \\
\hline
{\tt namp} & {\it char*} & name of the block to validate in the associative table. 
If {\tt namp='~'}, all the blocks in the associative table are verified in a recursive way. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\subsection{Interrogation of LCM objects}

The data structures in an LCM object are self-described. It is therefore possible to
interrogate them in order to know their characteristics.

\vskip 0.4cm

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{type of interrogation} \\
\cline{3-4}
\multicolumn{2}{c|}{} & father structure~~~~ & information block \\
\hline
father & associative table & {\tt lcminf\_c} & {\tt lcmlen\_c} \\
       &                   & {\tt lcmnxt\_c} &              \\
\cline{2-4}
       & heterogeneous list  & {\tt lcminf\_c} & {\tt lcmlel\_c} \\
\hline
\end{tabular}
\end{center}

\subsubsection{lcmlen\_c\index{lcmlen\_c}}

Function used to recover the length and type of an information block stored in an
associative table (either memory-resident or persistent). The length is the number of
elements in a daughter heterogeneous list or the number of elements in an array of elementary type.
If {\tt itylcm=3}, the length is the number of four-character words. As an example, the length required
to store an array of eight-character words is twice its dimension.

\begin{verbatim}

lcmlen_c(iplist,namp,ilong,itylcm);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} & name of the block. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ilong} & {\it int\_32*} & length of the block. =$-1$ for a daughter associative table; 
                                    =$N$ for a daughter heterogeneous list containing $N$ components; 
		                 =0 if the block does't exist. \\
\hline
{\tt itylcm} & {\it int\_32*} & type of information. =0 associative table; =1 32-bit integer; 
                                    =2 32-bit real; =3 4-character data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =10 heterogeneous list; 
				    =99 undefined (99 is returned if the block does't exist). \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcminf\_c\index{lcminf\_c}}

Function used to recover general information about a LCM object.

\begin{verbatim}

lcminf_c(iplist,namlcm,nammy,empty,ilong,lcm,access);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table or of the heterogeneous list. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt namlcm} & {\it char[73]} & name of the LCM object. \\
\hline
{\tt nammy} & {\it char[13]} & name of the associative table at address {\tt iplist}. $=${\tt '/'} if the associative table
is the root of the LCM object; $=${\tt ' '} if the associative table
is an heterogeneous list component. \\
\hline
{\tt empty} & {\it int\_32*} & 32-bit integer variable set to $1$ 
                            if the associative table is empty
			    or set to $0$ otherwise. \\
\hline
{\tt ilong} & {\it int\_32*} & $=-1$: {\tt iplist} is an associative table; $>0$: number of components in the heterogeneous list {\tt iplist}. \\
\hline
{\tt lcm} & {\it int\_32*} & 32-bit integer variable set to $1$ 
                                  if information is memory-resident or set to $0$ if information is persistent (stored in an XSM file). \\
\hline
{\tt access} & {\it int\_32*} & 32-bit integer variable set to the access mode of object. $=0$: the object
is closed (only available for memory-resident LCM objects); $=1$: the object is open for modification;
$=2$: the object is open in read-only mode.\\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmnxt\_c\index{lcmnxt\_c}}

Function used to find the name of the next block of data in an associative table. Use
of {\tt lcmnxt\_c} is forbidden if the associative table is empty. The order of names is
arbitrary. The search cycle indefinitely.

\begin{verbatim}

lcmnxt_c(iplist,namp);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} & name of an existing block. 
                                   {\tt namp=' '} can be used to obtain a first name to initiate the search. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt namp} & {\it char*} & name of the next block. 
          A call to {\tt xabort\_c} is performed if the associative table is empty. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmlel\_c\index{lcmlel\_c}}

Function used to recover the length and type of an information block stored in an
heterogeneous list (either memory-resident or persistent). The length is the number of
elements in a daughter heterogeneous list or the number of elements in an array of elementary type.
If {\tt itylcm=3}, the length is the number of four-character words. As an example, the length required
to store an array of eight-character words is twice its dimension.

\begin{verbatim}

lcmlel_c(iplist,iset,ilong,itylcm);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the block in the list.
The first element of the list is located at index $0$. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ilong} & {\it int\_32*} & length of the block. =0 if the block does't exist. \\
\hline
{\tt itylcm} & {\it int\_32*} & type of information. =0 associative table; =1 32-bit integer; 
                                    =2 32-bit real; =3 4-chatacter data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =10 heterogeneous list; 
				    =99 undefined (99 is returned if the block does't exist).  \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsection{Management of the array of elementary type}

Management of the array of elementary type can be performed {\sl with} copy of the data ({\tt lcmput\_c}, {\tt lcmget\_c}, {\tt lcmpdl\_c} or
{\tt lcmgdl\_c}) or {\sl without} copy ({\tt lcmppd\_c}, {\tt lcmgpd\_c}, {\tt lcmppl\_c} or
{\tt lcmgpl\_c}).

\vskip 0.4cm

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{type of operation} \\
\cline{3-4}
\multicolumn{2}{c|}{} & put~~~~~~~~~~~~~ & get~~~~~~~~~~~~~ \\
\hline
father & associative table & {\tt lcmput\_c} & {\tt lcmget\_c} \\
       &                   & {\tt lcmppd\_c} & {\tt lcmgpd\_c} \\
\cline{2-4}
       & heterogeneous list & {\tt lcmpdl\_c} & {\tt lcmgdl\_c} \\
       &                   & {\tt lcmppl\_c} & {\tt lcmgpl\_c} \\
\hline
\end{tabular}
\end{center}

\subsubsection{lcmget\_c\index{lcmget\_c}}

Function used to recover an information block (array of elementary type) from an associative table and to copy
this data into memory.

\begin{verbatim}

lcmget_c(iplist,namp,data);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} &  name of the block to recover. 
                                    A call to {\tt xabort\_c} is performed if the block does't exist. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt data} & {\it int\_32*} & array of dimension $\ge$ {\tt ilong} in which the block is copied. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\vskip 0.8cm

Function {\tt lcmget\_c} can be used to recover information of type other than {\it int\_32*} by using a
cast operation. Here is an example:

\begin{verbatim}
#include "lcm.h"
   ...
   float_32 data[5];
   lcm *iplist;
   iplist=... ;
   lcmget_c(&iplist,namp,(int_32*)data);
\end{verbatim}

\vskip 0.2cm

Function {\tt lcmget\_c} can also be used to recover character-string information available in a block
of the LCM object. It is also possible to use function {\tt lcmgcd\_c} presented in \Sect{lcmgcdc}.
In the following example, a block is stored in an associative table located at
address {\tt iplist}. The block has a name {\tt namp} and a length equivalent to 5 32-bit words.
The information is recovered into the integer array {\tt idata} and transformed into a null-terminated
character string {\tt hname}  using the {\tt strcut\_c} utility:

\begin{verbatim}
#include "lcm.h"
   ...
   char *namp="...", hname[21];
   int_32 idata[5];
   lcm *iplist;
   iplist=... ;
   lcmget_c(&iplist,namp,idata);
   strcut_c(hname,(char *)idata,20);
\end{verbatim}

\subsubsection{lcmput\_c\index{lcmput\_c}}

Function used to store a block of data (array of elementary type) into an associative table. 
The information is copied from memory towards the LCM object. If the block already exists, it is replaced;
otherwise, it is created. This operation cannot be performed into a LCM object open in {\tt read-only} mode.

\begin{verbatim}

lcmput_c(iplist,namp,ilong,itylcm,data);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} & name of the block. \\
\hline
{\tt ilong} & {\it int\_32} & length of the block. \\
\hline
{\tt itylcm} & {\it int\_32} & type of information. =1 32-bit integer; 
                                    =2 32-bit real; =3 4-character data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =99 undefined. \\
\hline
{\tt data} & {\it int\_32*} & array of dimension $\ge$ {\tt jlong} to be copied into the LCM object. {\tt jlong}={\tt 2*ilong} if {\tt itylcm}=4 or {\tt itylcm}=6;
                                   {\tt jlong}={\tt ilong} otherwise.
                                   Array elements {\tt data[0]} to {\tt data[jlong-1]}
                                   must be initialized before the call to {\tt lcmput\_c}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\vskip 0.4cm

Function {\tt lcmput\_c} can be used to store information of type other than {\it int\_32*} by using a
cast operation. Here is an example:

\begin{verbatim}
#include "lcm.h"
   ...
   float_32 data[5];
   lcm *iplist;
   int_32 i;
   iplist=... ;
   for (i=0;i<5;i++) {
     data[i]=... ;
   }
   lcmput_c(&iplist,namp,5,2,(int_32*)data);
\end{verbatim}

\vskip 0.2cm

Function {\tt lcmput\_c} can also be used to store character-string information in an associative table
of a LCM object. It is also possible to use function {\tt lcmpcd\_c} presented in \Sect{lcmpcdc}. In the
following example, a character string {\tt hname} is first transformed into an integer array {\tt idata}
using the {\tt strfil\_c} utility. This array (block of data) is stored into the LCM object located at
address {\tt iplist}, using {\tt lcmput\_c}. The block has a name {\tt namp}, a length equivalent
to 5 32-bit words, and a type equal to 3.

\begin{verbatim}
#include "lcm.h"
   ...
   char *namp="...", hname[20];
   int_32 idata[5], il=5, it=3;
   lcm *iplist;
   iplist=... ;
   strfil_c((char *)idata,hname,20);
   lcmput_c(&iplist,namp,il,it,idata);
\end{verbatim}

\subsubsection{lcmgpd\_c\index{lcmgpd\_c}}

Function used to recover the memory address of an information block (array of elementary type) from an associative table,
{\sl without} making a copy of the information. Use of this function must respect the following rules:
\begin{itemize}
\item If the information is modified after the call to {\tt lcmgpd\_c}, a call to {\tt lcmppd\_c} 
must be performed to acknowledge the modification.
\item The block {\tt *iofset} should never be released using a deallocation function such as
{\tt rlsara\_c}, {\tt free}, etc.
\item The address {\tt iofset} must never be copied into another variable.
\end{itemize}
Non respect of these rules may cause execution failure (core dump,
segmentation fault, etc) without possibility to throw an exception.

\vskip 0.2cm

A call to {\tt lcmgpd\_c} doesn't cause any modification to the LCM object.
The data array information is accessed directly from memory locations {\tt *iofset[0]} to {\tt *iofset[ilong-1]}
where {\tt iofset} is the address returned by function {\tt lcmgpd\_c}.

\begin{verbatim}

lcmgpd_c(iplist,namp,iofset);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} & name of the block to recover.
                                  A call to {\tt xabort\_c} is performed if the block does't exist. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt iofset} & {\it int\_32**} & address of the data array. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmppd\_c\index{lcmppd\_c}}

Function used to store a block of data (array of elementary type) into an associative table
{\sl without} making a copy of the information. If the block already exists, it is replaced;
otherwise, it is created. This operation cannot be performed into a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

{\sl If a block named {\tt namp} already exists in the associative table, the address associated
with {\tt namp} is replaced by the new address and the information pointed by the old address
is deallocated.}

\vskip 0.2cm

The array containing information stored by {\tt lcmppd\_c} {\sl must be} originally
allocated by a call of the form 
{\tt iofset = setara\_c(jlong)} or {\tt iofset = (int\_32*)malloc(jlong*sizeof(int\_32))}.
where {\tt jlong} is generally equal to {\tt ilong} except if
{\tt itylcm}=4 or {\tt itylcm}=6 where {\tt jlong}={\tt 2*ilong}.

\begin{verbatim}

lcmppd_c(iplist,namp,ilong,itylcm,iofset);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} & name of the block. \\
\hline
{\tt ilong} & {\it int\_32} & length of the block. \\
\hline
{\tt itylcm} & {\it int\_32} & type of information. =1 32-bit integer; 
                                    =2 32-bit real; =3 4-character data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =99 undefined. \\
\hline
{\tt iofset} & {\it int\_32*} & address of the data array of length {\tt jlong}, as returned by {\tt setara\_c}. {\tt jlong}={\tt 2*ilong}
                                   if {\tt itylcm}=4 or {\tt itylcm}=6; {\tt jlong}={\tt ilong} otherwise.
                                   Data elements {\tt iofset[0]} to {\tt iofset[jlong-1]} 
				   must be initialized before the call to {\tt lcmppd\_c}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\vskip 0.4cm

The information block of address {\tt iofset} will automatically be deallocated using function {\tt rlsara\_c} 
at closing time of the LCM object. Situations exist where this block is shared with data structures other
than LCM, and where the block must {\sl not} be deallocated by the {\sc lcm} API. In this case, it is imperative
to follow the call to {\tt lcmppd\_c} by a call to function {\tt refpush} of the form:
 
\begin{verbatim}
refpush(iplist,iofset);
\end{verbatim}

\subsubsection{lcmdel\_c\index{lcmdel\_c}}

Function used to erase an information block or a daughter heterogeneous list stored in a memory-resident associative table.
Function {\tt lcmdel\_c} {\sl cannot} be used with persistent LCM objects.

\begin{verbatim}

lcmdel_c(iplist,namp);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} & name of the block to erase. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmgdl\_c\index{lcmgdl\_c}}

Function used to recover an information block (array of elementary type) from an heterogeneous list and to copy
this data into memory.

\begin{verbatim}

lcmgdl_c(iplist,iset,data);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the block in the heterogeneous list. A call to {\tt xabort\_c} 
                                   is performed if the block does't exist.
The first element of the list is located at index $0$. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt data} & {\it int\_32*} & array of dimension $\ge$ {\tt ilong} in which the block is copied. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\vskip 0.4cm

Function {\tt lcmgdl\_c} can be used to recover character-string information available in a block
of the LCM object. It is also possible to use subroutine {\tt lcmgcl\_c} presented in \Sect{lcmgclc}. In the following example, a block is stored in an the heterogeneous list located at
address {\tt iplist}. The block is located at the {\tt iset}--th position of the heterogeneous list and has a length equivalent to 5 32-bit words.
The information is recovered into the integer array {\tt idata} and transformed into a null-terminated
character string {\tt hname}  using the {\tt strcut\_c} utility:

\begin{verbatim}
#include "lcm.h"
   ...
   char *namp="...", hname[21];
   int_32 iset,idata[5];
   lcm *iplist;
   iplist=... ;
   iset=...;
   lcmgdl_c(&iplist,iset,idata);
   strcut_c(hname,(char *)idata,20);
\end{verbatim}

\subsubsection{lcmpdl\_c\index{lcmpdl\_c}}

Function used to store a block of data (array of elementary type) into an heterogeneous list. 
The information is copied from memory towards the LCM object. If the block already exists, it is replaced;
otherwise, it is created. This operation cannot be performed into a LCM object open in {\tt read-only} mode.

\begin{verbatim}

lcmpdl_c(iplist,iset,ilong,itylcm,data);
\end{verbatim}

\vskip 0.2cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the block in the list.
The first element of the list is located at index $0$. \\
\hline
{\tt ilong} & {\it int\_32} & length of the block. \\
\hline
{\tt itylcm} & {\it int\_32} & type of information. =1 32-bit integer; 
                                    =2 32-bit real; =3 4-character data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =99 undefined. \\
\hline
{\tt data} & {\it int\_32*} & array of dimension $\ge$ {\tt ilong} to be copied into the LCM object. {\tt jlong}={\tt 2*ilong}
                                   if {\tt itylcm}=4 or {\tt itylcm}=6; {\tt jlong}={\tt ilong} otherwise.
                                   Array elements {\tt data[0]} to {\tt data[jlong-1]}
                                   must be initialized before the call to {\tt lcmpdl\_c}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\vskip 0.4cm

Function {\tt lcmpdl\_c}  can be used to store character-string information into an heterogeneous list of a LCM object. In the
following example, a character string {\tt hname} is first transformed into an integer array {\tt idata}
using the {\tt strfil\_c} utility. This array (block of data) is stored into the LCM object located at
address {\tt iplist}, using {\tt lcmpdl\_c} . The block is located at the {\tt iset}--th position of the heterogeneous list, has a length equivalent to 5 32-bit words, and a type
equal to 3.

\begin{verbatim}
#include "lcm.h"
   ...
   char *namp="...", hname[20];
   int_32 iset,idata[5],it=3,il=5;
   lcm *iplist;
   iplist=... ;
   iset=...;
   strfil_c((char *)idata,hname,20);
   lcmpdl_c(&iplist,iset,il,it,idata);
\end{verbatim}

\subsubsection{lcmgpl\_c\index{lcmgpl\_c}}

Function used to recover the memory address of an information block (array of elementary type) from an heterogeneous list,
{\sl without} making a copy of the information. Use of this function must respect the following rules:
\begin{itemize}
\item If the information is modified after the call to {\tt lcmgpl\_c}, a call to {\tt lcmppl\_c} 
must be performed to acknowledge the modification.
\item The block {\tt *iofset} should never be released using a deallocation function such as
{\tt rlsara\_c}, {\tt free}, etc.
\item The address {\tt iofset} must never be copied into another variable.
\end{itemize}
Non respect of these rules may cause execution failure (core dump,
segmentation fault, etc) without possibility to throw an exception.

\vskip 0.2cm

A call to {\tt lcmgpl\_c} doesn't cause any modification to the LCM object.
The data array information is accessed directly from memory locations {\tt *iofset[0]} to {\tt *iofset[ilong-1]}
where {\tt iofset} is the address returned by function {\tt lcmgpl\_c}.

\begin{verbatim}

lcmgpl_c(iplist,iset,iofset);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the block in the list.
A call to {\tt xabort\_c} is performed if the block does't exist.
The first element of the list is located at index $0$. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt iofset} & {\it int\_32**} & address of the data array, as returned by {\tt setara\_c}. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmppl\_c\index{lcmppl\_c}}

Function used to store a block of data (array of elementary type) into an heterogeneous list
{\sl without} making a copy of the information. If the block already exists, it is replaced;
otherwise, it is created. This operation cannot be performed into a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

{\sl If the {\tt iset}-th component of the heterogeneous list already exists, the address associated
with this component  is replaced by the new address and the information pointed by the old address
is deallocated.}

\vskip 0.2cm

The array containing information stored by {\tt lcmppl\_c} {\sl must be} originally
allocated by a call of the form 
{\tt iofset = setara\_c(jlong)} or {\tt iofset = (int\_32*)malloc(jlong*sizeof(int\_32))}
where {\tt jlong} is generally equal to {\tt ilong} except if
{\tt itylcm}=4 or {\tt itylcm}=6 where {\tt jlong}={\tt 2*ilong}.
 
\begin{verbatim}

lcmppl_c(iplist,iset,ilong,itylcm,iofset);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the block in the list.
The first element of the list is located at index $0$. \\
\hline
{\tt ilong} & {\it int\_32} & length of the block. \\
\hline
{\tt itylcm} & {\it int\_32} & type of information. =1 32-bit integer; 
                                    =2 32-bit real; =3 4-character data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex;
				    =99 undefined. \\
\hline
{\tt iofset} & {\it int\_32*} & address of the data array, as returned by {\tt setara\_c}. {\tt jlong}={\tt 2*ilong}
                                   if {\tt itylcm}=4 or {\tt itylcm}=6; {\tt jlong}={\tt ilong} otherwise.
                                   Data elements {\tt iofset[0]} to {\tt iofset[jlong-1]} 
				   must be initialized before the call to {\tt lcmppl\_c}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\vskip 0.4cm

The information block of address {\tt iofset} will automatically be deallocated using function  {\tt rlsara\_c} 
at closing time of the LCM object. Situations exist where this block is shared with data structures other
than LCM, and where the block must {\sl not} be deallocated by the {\sc lcm} API. In this case, it is imperative
to follow the call to {\tt lcmppl\_c} by a call to function {\tt refpush} of the form:

\begin{verbatim}
refpush(iplist,iofset);
\end{verbatim}

\subsection{Management of the associative tables and of the heterogeneous lists}

These functions permit to create ({\tt lcmsix\_c}, {\tt lcmdid\_c}, {\tt lcmdil\_c},
{\tt lcmlid\_c}, {\tt lcmlil\_c}) or to access ({\tt lcmsix\_c}, {\tt lcmgid\_c}, {\tt lcmgil\_c})
daughter associative tables or daughter heterogeneous lists. Use of these functions is summarized in the following table:

\vskip 0.4cm

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{daughter} \\
\cline{3-4}
\multicolumn{2}{c|}{} & associative table & heterogeneous list \\
\hline
father & associative table & {\tt lcmdid\_c} & {\tt lcmlid\_c} \\
       &                   & {\tt lcmgid\_c} & {\tt lcmgid\_c} \\
\cline{2-4}
       &heterogeneous list & {\tt lcmdil\_c} & {\tt lcmlil\_c} \\
       &                   & {\tt lcmgil\_c} & {\tt lcmgil\_c} \\
\hline
\end{tabular}
\end{center}

\subsubsection{lcmdid\_c\index{lcmdid\_c}}

Function used to create or access a daughter associative table included into a father associative table. This operation cannot be
performed in a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

The daughter associative table is created if it doesn't already exist. Otherwise, the
existing daughter associative table is accessed. In the latter case, it is recommended
to use function {\tt lcmgid\_c} which is faster for a simple access and which can be used
with LCM object open in {\tt read-only} mode.

\begin{verbatim}

lcmdid_c(iplist,namp);
\end{verbatim}

\vskip 0.5cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameterss:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the father associative table. \\
\hline
{\tt namp} & {\it char*} & name of the daughter associative table. \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it lcm*} & address of the daughter associative table. \\
\hline
\end{tabular}

\subsubsection{lcmlid\_c\index{lcmlid\_c}}

Function used to create or access a daughter heterogeneous list included into a father associative table. This operation cannot be
performed in a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

In the following example, a daughter heterogeneous list is created as a block {\tt LIST}
into a father associative table. The heterogeneous list contains 5~components. A block of data
is stored in each component of the heterogeneous list using {\tt lcmppl\_c}:

\begin{verbatim}
#include "lcm.h"
   ...
   lcm *iplist,*jplist;
   int_32 n=5, i ;
   ...
   jplist=lcmlid_c(&iplist,"LIST",n);
   for(i=0;i<5;i++) {
     lcmppl_c(&jplist,i,...
   }
\end{verbatim}

\vskip 0.2cm

The heterogeneous list capability is implemented through calls to function {\tt lcmlid\_c}. Such a
call permit the following possibilities:
\begin{itemize}
\item the heterogeneous list is created if it doesn't already exist.
\item the heterogeneous list is accessed if it already exists {\sl and} if its length is unchanged. In this case,
it is recommended to use function {\tt lcmgid\_c} which is faster for a simple access and which can be used
with LCM object open in {\tt read-only} mode.
\item the heterogeneous list is enlarged (components are added) if it already exists {\sl and} if the new length is larger than the preceding one.
\end{itemize}

\begin{verbatim}

lcmlid_c(iplist,namp,ilong);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameterss:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the father associative table. \\
\hline
{\tt namp} & {\it char*} & name of the daughter heterogeneous list. \\
\hline
{\tt ilong} & {\it int\_32} & number of components in the daughter heterogeneous list.\\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it lcm*} & address of the daughter heterogeneous list named {\tt namp}. \\
\hline
\end{tabular}

\subsubsection{lcmlil\_c\index{lcmlil\_c}}

Function used to create or access a daughter heterogeneous list included into a father heterogeneous list. This operation cannot be
performed in a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

In the following example, a daughter heterogeneous list is created as {\tt 77}-th component
of a father heterogeneous list. The heterogeneous list contains 5~components. A block of data
is stored in each component of the heterogeneous list using {\tt lcmppl\_c}:

\begin{verbatim}
#include "lcm.h"
   ...
   lcm *iplist,*jplist;
   int_32 n=5, i, iset=77 ;
   ...
   jplist=lcmlil_c(&iplist,iset,n);
   for(i=0;i<5;i++) {
     lcmppl_c(&jplist,i,...
   }
\end{verbatim}

\vskip 0.2cm

The heterogeneous list capability is implemented through calls to function {\tt lcmlil\_c}. Such a
call permit the following possibilities:
\begin{itemize}
\item the heterogeneous list is created if it doesn't already exist.
\item the heterogeneous list is accessed if it already exists {\sl and} if its length is unchanged. In this case,
it is recommended to use function {\tt lcmgil\_c} which is faster for a simple access and which can be used
with LCM object open in {\tt read-only} mode.
\item the heterogeneous list is enlarged (components are added) if it already exists {\sl and} if the new length is larger than the preceding one.
\end{itemize}

\begin{verbatim}

lcmlil_c(iplist,iset,ilong);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameterss:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the father heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the daughter heterogeneous list in the father heterogeneous list.
The first element of the list is located at index $0$. \\
\hline
{\tt ilong} & {\it int\_32} & number of components in the daughter heterogeneous list. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it lcm*} & address of the daughter heterogeneous list. \\
\hline
\end{tabular}

\subsubsection{lcmdil\_c\index{lcmdil\_c}}

Function used to create or access a daughter associative table included into a father heterogeneous list. This operation cannot be
performed in a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

The daughter associative table is created if it doesn't already exist. Otherwise, the
existing daughter associative table is accessed. In the latter case, it is recommended
to use function {\tt lcmgil\_c} which is faster for a simple access and which can be used
with LCM object open in {\tt read-only} mode.

\vskip 0.2cm

It is a good programming practice to replace a set of $N$ distinct associative tables by a
list made of $N$ associative tables, as depicted in \Fig{f1}.

\vskip 0.2cm

In the example of \Fig{f1}, a set of 5~associative tables, created by {\tt lcmdid\_c}:
\begin{verbatim}
#include "lcm.h"
   ...
   char HDIR[13]
   lcm*iplist,*kplist ;
   int_32 i;
   HDIR[12] = '\0';
   for(i=0;i<5;i++) {
     (void)sprintf(HDIR,"GROUP%3d/  5",i+1);
     kplist=lcmsix_c(&iplist,HDIR);
     lcmppd_c(&kplist,...);
       ...
   }
\end{verbatim}

\noindent are replaced by a list of 5~associative tables, created by {\tt lcmlid\_c} and {\tt lcmdil\_c}:

\begin{verbatim}
#include "lcm.h"
      ...
      lcm *iplist,*jplist,*kplist;
      int_32 n=5 ;
      jplist=lcmlid_c(&iplist,'GROUP',n);
      for(i=0;i<5;i++) {
       kplist=lcmdil_c(&jplist,i);
       lcmppd_c(&kplist,...);
      }
\end{verbatim}

\vskip 0.2cm

\begin{figure}[htbp]
\begin{center} 
\epsfxsize=9cm
\centerline{ \epsffile{vect.eps}}
\parbox{12cm}{\caption{A list of associative tables.}\label{fig:f1}}   
\end{center}  
\end{figure}

\vskip 0.2cm

The capability to include associative tables into an heterogeneous list is implemented using
the {\tt lcmdil\_c} function:

\begin{verbatim}

lcmdil_c(iplist,iset);
\end{verbatim}

\vskip 0.5cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameterss:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the father heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the daughter associative table in the father heterogeneous list.
The first element of the list is located at index $0$.  \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it lcm*} & address of the daughter associative table. \\
\hline
\end{tabular}

\subsubsection{lcmgid\_c\index{lcmgid\_c}}

Function used to access a daughter associative table {\sl or} heterogeneous list included into a father associative table. 

\begin{verbatim}

lcmgid_c(iplist,namp);
\end{verbatim}

\vskip 0.5cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameterss:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the father associative table. \\
\hline
{\tt namp} & {\it char*} & name of the daughter associative table or heterogeneous list. \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it lcm*} & address of the daughter associative table or heterogeneous list.  A call to {\tt xabort\_c} is performed if this daughter doesn't extst. \\
\hline
\end{tabular}

\subsubsection{lcmgil\_c\index{lcmgil\_c}}

Function used to access a daughter associative table {\sl or} heterogeneous list included into a father heterogeneous list. 

\begin{verbatim}

lcmgil_c(iplist,iset);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameterss:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the father heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the daughter associative table or heterogeneous list in the father heterogeneous list.
The first element of the list is located at index $0$.  \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it lcm*} & address of the daughter associative table or heterogeneous list. A call to {\tt xabort\_c} is performed if this daughter doesn't extst. \\
\hline
\end{tabular}

\subsubsection{lcmsix\_c\index{lcmsix\_c}}

Function used to move across the hierarchical structure of a LCM object made of
associative tables. Using this function, there is no need to remember the names of
the father (grand-father, etc.) associative tables. If a daughter associative table doesn't
exist and if the LCM object is open on creation or modification mode, the daughter
associative table is created. A daughter associative table cannot be created if the
LCM object is open in {\tt read-only} mode.

\vskip 0.4cm

Function {\tt lcmsix\_c} is deprecated, as {\tt lcmdid\_c} offers a more elegant way to perform the same operation.
However, {\tt lcmsix\_c} is kept available in the {\sc lcm} API for historical reasons.

\begin{verbatim}

lcmsix_c(iplist,namp,iact);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table before the call to {\tt lcmsix\_c}. \\
\hline
{\tt namp} & {\it char**} & name of the daughter associative table if {\tt iact=1}. 
                                   This parameter is not used if {\tt iact=0} or {\tt iact=2}. \\
\hline
{\tt iact} & {\it int\_32} & type of move: =0 return towards the root directory of the LCM object; 
                                   =1 move towards the daughter associative table (create it if it doesn't exist); 
				   =2 return towards the father associative table. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt iplist} & lcm** & address of the associative table after the call to {\tt lcmsix\_c}. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\vspace{0.4cm}

\subsection{LCM utility functions}

\subsubsection{lcmlib\_c\index{lcmlib\_c}}

Function used to print (towards {\tt stdout}) the content of the active directory of an associative table or heterogeneous list.

\begin{verbatim}

lcmlib_c(iplist);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table or of the heterogeneous list. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmequ\_c\index{lcmequ\_c}}

Function used to perform a deep-copy of the information contained in an associative table (address {\tt iplis1}) 
towards another associative table (address {\tt iplis2}). Note that the second associative table (address {\tt iplis2}) is modified
but not created by {\tt lcmequ\_c}.

\begin{verbatim}

lcmequ_c(iplis1,iplis2);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt iplis1} & {\it lcm**} & address of the existing associative table or of the heterogeneous list
                                    (accessed in {\tt read-only} mode). \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt iplis2} & {\it lcm**} & address of the associative table or of the heterogeneous list, modified by {\tt lcmequ\_c}. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmexp\_c\index{lcmexp\_c}}

Function used to export (or import) the content of an associative table towards (or from) a sequential file. The sequential file
can be in binary or {\tt ascii} format.

\vskip 0.4cm

The export of information starts from the active directoty. Note that {lcmexp\_c} is basically a serialization algorithm
based on the contour algorithm.

\begin{verbatim}

lcmexp_c(iplist,impx,file,imode,idir);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameterss:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table or of the heterogeneous list to be exported (or imported). \\
\hline
{\tt impx} & {\it int\_32} & print parameter (equal to 0 for no print). \\
\hline
{\tt file} & {\it FILE*} & sequential file. \\
\hline
{\tt imode} & {\it int\_32} & =1 binary sequential file; 
                                    =2 {\sc ascii} sequential file. \\
\hline
{\tt idir} & {\it int\_32} & =1 to export; =2 to import. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\subsection{Using variable-length string arrays}

The following functions are implemented using the C~functions of the preceding sections. They
permit the use of variable-length string arrays, a capability not yet available with the Fortran
{\sc lcm} API.

\vskip 0.4cm

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{type of operation} \\
\cline{3-4}
\multicolumn{2}{c|}{} & put~~~~~~~~~~~~~ & get~~~~~~~~~~~~~ \\
\hline
father & associative table & {\tt lcmpcd\_c} & {\tt lcmgcd\_c} \\
\cline{2-4}
       & heterogeneous list & {\tt lcmpcl\_c} & {\tt lcmgcl\_c} \\
\hline
\end{tabular}
\end{center}

\subsubsection{lcmgcd\_c\index{lcmgcd\_c}}\label{sect:lcmgcdc}

Function used to recover a variable-length string array from a block of data stored in an associative table.

\begin{verbatim}

lcmgcd_c(iplist,namp,hdata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} &  name of the variable-length string array
to recover. A call to {\tt xabort\_c} is performed if the block does't exist. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt hdata} & {\it char**} & variable-length string array of dimension $\ge$ {\tt ilong}. The memory space required to represent the string array is allocated by {\tt lcmgcd\_c}.\\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmpcd\_c\index{lcmpcd\_c}}\label{sect:lcmpcdc}

Function used to store a variable-length string array into a block of data stored in an associative table.
If the block of data already exists, it is updated; otherwise, it is created. This operation cannot be performed
in a LCM object open in {\tt read-only} mode.

\begin{verbatim}

lcmpcd_c(iplist,namp,ilong,hdata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the associative table. \\
\hline
{\tt namp} & {\it char*} &name of the variable-length string array
to store. \\
\hline
{\tt ilong} & {\it int\_32} & number of components in the variable-length string array.\\
\hline
{\tt hdata} & {\it char**} & array of dimension $\ge$ {\tt ilong} to be copied in the LCM object. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent Example:
\begin{verbatim}
#include "lcm.h"
   ...
   lcm *iplist;
   int_32 i, ilong = 5;
   char *hdata1[ilong],*hdata2[ilong];

   hdata1[0] = "string1";
   hdata1[1] = "  string2";
   hdata1[2] = "    string3";
   hdata1[3] = "      string4";
   hdata1[4] = "        string5";
   for (i=0;i<ilong;i++) {
     printf("i=%d string='%s' size=%d\n",i,hdata1[i],strlen(hdata1[i]));
   }

   lcmop_c(&iplist,"mon_dict",0,1,2);

   /* Store the information */
   lcmpcd_c(&iplist,"node1",ilong,hdata1);

   /* Recover the information */
   lcmgcd_c(&iplist,"node1",hdata2);

   for (i=0;i<ilong;i++) {
     printf("in table i=%d string='%s' size=%d\n",i,hdata2[i],strlen(hdata2[i]));
   }
   for (i=0;i<ilong;i++) free(hdata2[i]);
   lcmcl_c(&iplist,2);
\end{verbatim}

\subsubsection{lcmgcl\_c\index{lcmgcl\_c}}\label{sect:lcmgclc}

Function used to recover a variable-length string array from a block of data stored in an heterogeneous list.

\begin{verbatim}

lcmgcl_c(iplist,namp,hdata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} & index of the variable-length string array in the heterogeneous list. A call to {\tt xabort\_c} is performed if the component doesn't exist.
The first element of the list is located at index $0$. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt hdata} & {\it char**} & variable-length string array of dimension $\ge$ {\tt ilong}. The memory space required to represent the string array is allocated by {\tt lcmgcl\_c}.\\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{lcmpcl\_c\index{lcmpcl\_c}}\label{sect:lcmpclc}

Function used to store a variable-length string array into a block of data stored in an heterogeneous list.
If the block of data already exists, it is updated; otherwise, it is created. This operation cannot be performed
in a LCM object open in {\tt read-only} mode.

\begin{verbatim}

lcmpcl_c(iplist,iset,ilong,hdata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iplist} & {\it lcm**} & address of the heterogeneous list. \\
\hline
{\tt iset} & {\it int\_32} &index of the variable-length string array in the heterogeneous list.
The first element of the list is located at index $0$. \\
\hline
{\tt ilong} & {\it int\_32} & number of components in the variable-length string array .\\
\hline
{\tt hdata} & {\it char**} & array of dimension $\ge$ {\tt ilong} to be copied in the LCM object. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent Example:
\begin{verbatim}
#include "lcm.h"
   ...
   lcm *iplist, *jplist;
   int_32 i, ilong = 5;
   char *hdata1[ilong],*hdata2[ilong];

   hdata1[0] = "string1";
   hdata1[1] = "  string2";
   hdata1[2] = "    string3";
   hdata1[3] = "      string4";
   hdata1[4] = "        string5";
   for (i=0;i<ilong;i++) {
     printf("i=%d string='%s' size=%d\n",i,hdata1[i],strlen(hdata1[i]));
   }

   lcmop_c(&iplist,"mon_dict",0,1,2);

   /* Creation of the heterogeneous list */
   jplist = lcmlid_c(&iplist,"node2",77);

   /* Store the information */
   lcmpcl_c(&jplist,4,ilong,hdata1);

   /* Recover the information */
   lcmgcl_c(&jplist,4,hdata2);

   for (i=0;i<ilong;i++) {
     printf("in list i=%d string='%s' size=%d\n",i,hdata2[i],strlen(hdata2[i]));
   }
   for (i=0;i<ilong;i++) free(hdata2[i]);

   lcmcl_c(&iplist,2);
\end{verbatim}

\subsection{Dynamic allocation of the elementary blocks of data}

\subsubsection{setara\_c\index{setara\_c}}\label{sect:setara}

Function used to allocate a block of data for storing a memory-resident {\tt int\_32} data array.
Function {\tt setara\_c} is a simple wrapper for {\tt malloc} standard library function.
If the operating system fails to allocate the memory, a call to {\tt xabort\_c} is performed.

\begin{verbatim}

setara_c(ilong);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt ilong} & {\it int\_32} & length of the block of data to allocate in unit of 32-bit words. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it int\_32*} & address of the allocated block of data. \\
\hline
\end{tabular}

\subsubsection{rlsara\_c\index{rlsara\_c}}\label{sect:rlsara}

Function used to deallocate a memory-resident block of data previously allocated by {\tt setara\_c}.
The implementation of {\tt rlsara\_c} in ANSI~C is based on the {\tt free} standard library function. If the operating system fails to deallocate
the memory, a call to {\tt xabort\_c} is performed.

\begin{verbatim}

rlsara_c(iofset);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt iofset} & {\it int\_32*} & address of the block of data to deallocate. This value {\sl must} have been allocated by a previous call to {\tt setara\_c}. \\
\hline
\end{tabular}
\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\subsection{Abnormal termination of the execution}

\subsubsection{xabort\_c}

Function used to cause the program termination. A message describing the conditions of the
termination is printed.

\vskip 0.2cm

It is important to use this function to abort a program instead of using the {\tt exit()}
function of the standard library. The {\tt xabort\_c} function can be used to implement {\sl exception
treatment} in situations where the application software is driven by a multi-physics system.

\vskip 0.2cm

If an abnormal termination occurs, the {\tt xabort\_c} function is called as
\begin{verbatim}
      xabort_c("sub001: execution failure.");
\end{verbatim}

\begin{verbatim}

xabort_c(hsmg);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt hsmg} & {\it char*} & message describing the conditions of the abnormal termination. \\
\hline
\end{tabular}
\vskip 0.8cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\clearpage

\section {The ANSI C {\sc hdf5} API}\label{sect:hdf5apiC}

HDF5 is a hierarchical filesystem data format. HDF5 is self-describing, allowing an application to interpret the structure and contents
of a file with no outside information. A HDF5 file created on a little endian CPU can be read on a big endian CPU, and vice versa.
Similarly, real(4) datasets can be recovered in real(8) arrays, and vice versa. HDF5 includes two major types of object:
\begin{itemize}
\item Datasets, which are multidimensional arrays of a homogeneous type
\item Groups, which are container structures which can hold datasets and other groups.
\end{itemize}
The Ganlib5 implementation of HDF5 relies on the official ANSI C API provided by the HDF Group, a non-profit corporation whose mission
is to ensure continued development of HDF5 technologies and the continued accessibility of data stored in HDF.\opcite{hdf5} The Ganlib5 kernel
reimplements simplified ANSI C and Fortran bindings of the legacy HDF5 API to facilitate its use. The compilation and link edition of the
new bindings require the definition of a UNIX environment variables {\tt HDF5\_INC} and {\tt HDF5\_API} pointing towards directories containing
the official HDF5 {\tt include} and C API sub-directories compatible with your operating system. 

\begin{itemize}
\item On a OSX operating system, these variables may be set as
\begin{verbatim}
export HDF5_INC="/usr/local/Cellar/hdf5/1.12.1/include" # HDF5 include directory
export HDF5_API="$HDF5_INC/../lib"                      # HDF5 C API
\end{verbatim}
\item On a Linux RedHat operating system, these variables may be set as
\begin{verbatim}
export HDF5_INC="/usr/local/hdf5/include" # HDF5 include directory
export HDF5_API="$HDF5_INC/../lib"        # HDF5 C API
\end{verbatim}
\item On a Linux Scibian operating system, these variables may be set as
\begin{verbatim}
export HDF5_INC="/usr/include/hdf5/serial"              # HDF5 include directory
export HDF5_API="/usr/lib/x86_64-linux-gnu/hdf5/serial" # HDF5 C API
\end{verbatim}
\item On a Unix AIX operating system, these variables may be set as
\begin{verbatim}
export HDF5_INC="/usr/include"     # HDF5 include directory
export HDF5_API="$HDF5_INC/../lib" # HDF5 C API
\end{verbatim}
\end{itemize}
On Linux and AIX systems, the environment variable {\tt LD\_LIBRARY\_PATH} must also be set:
\begin{verbatim}
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HDF5_API"
\end{verbatim}

Any ANSI C program using the Ganlib5 HDF5 API implementation should use the following include:
\begin{verbatim}
#include "hdf5_aux.h"
\end{verbatim}

\vskip 0.08cm

\subsection{Opening and closing of HDF5 files}

\subsubsection{hdf5\_open\_file\_c}

Open a HDF5 file. Obtain the address of the HDF5 file if it is created. Note that CLE-2000 is responsible to perform the calls to
{\tt hdf5\_open\_file\_c} for the HDF5 files that are used as parameters of a CLE-2000 module. The use
of {\tt hdf5\_open\_file\_c} is generally restricted to the use of temporary HDF5 files created within a CLE-2000 module.

\begin{verbatim}

hdf5_open_file_c(fname, ifile, irdonly);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt fname} & {\it char[1024]} & name of the HDF5 file. \\
\hline
{\tt irdonly} & {\it int\_32} & =0 to create a new HDF5 file or to to modify an existing HDF5 file. A file is not created if it does not already exist. 
				=1 to access an existing HDF5 file in {\bf read-only} mode. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
\end{tabular}

\subsubsection{hdf5\_close\_file\_c}

Close a HDF5 file. Note that CLE-2000 is responsible to perform the calls to
{\tt hdf5\_close\_file\_c} for the HDF5 files that are used as parameters of a CLE-2000 module. The use
of {\tt hdf5\_close\_file\_c} is generally restricted to the use of temporary HDF5 files created within a CLE-2000 module.

\begin{verbatim}

hdf5_close_file_c(ifile);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
\end{tabular}

\subsection{Interrogation of HDF5 files}

The data structures in a HDF5 file are self-described. It is therefore possible to interrogate them in order to know their characteristics.

\subsubsection{hdf5\_list\_c}

List the root table of contents of a group on the standard output. The name of a group can include one or many path separators (character~$\slash$)
to list different hierarchical levels.

\begin{verbatim}

hdf5_list_c(ifile, namp);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a group. \\
\hline
\end{tabular}

\subsubsection{hdf5\_get\_dimensions\_c}

Find the rank (number of dimensions) of a dataset.

\begin{verbatim}

hdf5_get_dimensions_c(ifile, namp, rank);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt rank} & {\it int\_32*} & rank of the dataset. \\
\hline
\end{tabular}

\subsubsection{hdf5\_get\_num\_group\_c}

Find the number of objects (daughter datasets {\sl and} daughter groups) in a group.

\begin{verbatim}

hdf5_get_num_group_c(ifile, namp, nbobj);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a group. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt nbobj} & {\it int\_32*} & number of objects in group {\tt namp}. \\
\hline
\end{tabular}

\subsubsection{hdf5\_list\_datasets\_c}

Recover character daughter dataset names in a group.

\begin{verbatim}

hdf5_list_datasets_c(file, namp, ndsets, idata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a group. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt nbobj} & {\it int\_32*} & number of daughter datasets in group {\tt namp}. \\
\hline
{\tt idata} & {\it char*} & list of character names of each daughter dataset. Each name is null terminated. \\
\hline
\end{tabular}

\subsubsection{hdf5\_list\_groups\_c}

Recover character daughter groups names in a group.

\begin{verbatim}

hdf5_list_groups_c(file, namp, ndsets, idata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a group. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt nbobj} & {\it int\_32*} & number of daughter groups in group {\tt namp}. \\
\hline
{\tt idata} & {\it char*} & list of character names of each daughter group. Each name is null terminated. \\
\hline
\end{tabular}

\subsubsection{hdf5\_info\_c}

Find dataset information.

\begin{verbatim}

hdf5_info_c(ifile, namp, rank, type, nbyte, dimsr);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt rank} & {\it int\_32*} & rank (number of dimensions) of dataset. \\
\hline
{\tt type} & {\it int\_32*} & type of dataset: =1 32-bit integer; 
                                    =2 32-bit real; =3 character data; 
				    =4 64-bit real. \\
\hline
{\tt nbyte} & {\it int\_32*} & number of bytes in each component of the dataset. \\
\hline
{\tt dimsr} & {\it int\_32*} & integer array containing the dimension of dataset. {\tt rank} values are provided. \\
\hline
\end{tabular}

\subsubsection{hdf5\_group\_exists\_c}

Test for existence of a group.

\begin{verbatim}

ierr = hdf5_group_exists_c(ifile, namp);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a group. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt ierr} & {\it int\_32*} & existence flag: =0/1 the group does/does not exist. \\
\hline
\end{tabular}

\vskip 0.8cm

\subsection{Management of groups and datatypes}

\subsubsection{hdf5\_create\_group\_c}

Create a group.

\begin{verbatim}

hdf5_create_group_c(ifile, namp);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of the group to create. \\
\hline
\end{tabular}

\vskip 0.8cm

\subsubsection{hdf5\_read\_data\_int\_c}

Copy an integer dataset from HDF5 file into memory.

\begin{verbatim}

hdf5_read_data_int_c(ifile, namp, idata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt idata} & {\it int\_32*} & integer array. \\
\hline
\end{tabular}

\subsubsection{hdf5\_read\_data\_real4\_c}

Copy a real(4) dataset from HDF5 file into memory.

\begin{verbatim}

hdf5_read_data_real4_c(ifile, namp, rdata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt rdata} & {\it float*} & real(4) array. \\
\hline
\end{tabular}

\subsubsection{hdf5\_read\_data\_real8\_c}

Copy a real(8) dataset from HDF5 file into memory.

\begin{verbatim}

hdf5_read_data_real8_c(ifile, namp, rdata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt rdata} & {\it double*} & real(8) array. \\
\hline
\end{tabular}

\subsubsection{hdf5\_read\_data\_string\_c}

Copy a character dataset from HDF5 file into memory.

\begin{verbatim}

hdf5_read_data_string_c(ifile, namp, idata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt idata} & {\it char*} & character array. \\
\hline
\end{tabular}

\subsubsection{hdf5\_write\_data\_int\_c}

Copy an integer array from memory into a HDF5 dataset

\begin{verbatim}

hdf5_write_data_int_c(ifile, namp, rank, dimsr, idata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
{\tt rank} & {\it int\_32*} & rank (number of dimensions) of dataset. \\
\hline
{\tt dimsr} & {\it int\_32*} & integer array containing the dimension of dataset. {\tt rank} values are provided. \\
\hline
{\tt idata} & {\it int\_32*} & integer array. \\
\hline
\end{tabular}

\subsubsection{hdf5\_write\_data\_real4\_c}

Copy a real(4) array from memory into a HDF5 dataset

\begin{verbatim}

hdf5_write_data_real4_c(ifile, namp, rank, dimsr, rdata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
{\tt rank} & {\it int\_32*} & rank (number of dimensions) of dataset. \\
\hline
{\tt dimsr} & {\it int\_32*} & integer array containing the dimension of dataset. {\tt rank} values are provided. \\
\hline
{\tt rdata} & {\it float*} & real(4) array. \\
\hline
\end{tabular}

\subsubsection{hdf5\_write\_data\_real8\_c}

Copy a real(8) array from memory into a HDF5 dataset

\begin{verbatim}

hdf5_write_data_real8_c(ifile, namp, rank, dimsr, rdata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
{\tt rank} & {\it int\_32*} & rank (number of dimensions) of dataset. \\
\hline
{\tt dimsr} & {\it int\_32*} & integer array containing the dimension of dataset. {\tt rank} values are provided. \\
\hline
{\tt rdata} & {\it double*} & real(8) array. \\
\hline
\end{tabular}

\subsubsection{hdf5\_write\_data\_string\_c}

Copy an character array from memory into a HDF5 dataset

\begin{verbatim}

hdf5_write_data_string_c(ifile, namp, rank, dimsr, idata);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it hid\_t*} & HDF5 file identifier. \\
\hline
{\tt namp} & {\it char[1024]} & name of a dataset. \\
\hline
{\tt rank} & {\it int\_32*} & rank (number of dimensions) of dataset. \\
\hline
{\tt len} & {\it int\_32*} & length of a string element in the array (in bytes). \\
\hline
{\tt dimsr} & {\it int\_32*} & integer array containing the dimension of dataset. {\tt rank} values are provided. \\
\hline
{\tt idata} & {\it char*} & character array. \\
\hline
\end{tabular}

\clearpage

\section {The ANSI C CLE-2000 API}\label{sect:cle2000apiC}

\subsection {The main entry point for CLE-2000}

The CLE-2000 supervisor have been entirely reprogrammed in ANSI~C in its GANLIB Version 5 implementation. Its main entry
point is function {\tt cle2000\_c()} that can be used to execute a {\sl CLE-2000 source file} which can be a {\sl main procedure}
(a sequential {\sc ascii} file with {\tt .x2m} suffix) or a {\sl parametrized procedure} (a sequential {\sc ascii} file with {\tt .c2m} suffix).
Parametrized procedures can be called by function {\tt cle2000\_c()} or by other CLE-2000 procedures. Function {\tt cle2000\_c()} is therefore 
recursive. A computational scheme is a set of parametrized procedures.

\subsubsection{cle2000\_c\index{cle2000\_c}}

The general specification of function {\tt cle2000\_c()} is

\begin{verbatim}

cle2000_c(ilevel, dummod, filenm, iprint, my_param);
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ilevel} & {\it int\_32} & recursivity level of {\tt cle2000\_c()} call. We recommend to call
{\tt cle2000\_c()} from the main entry point with {\tt ilevel = 1}. \\
\hline
{\tt dummod} & {\it int\_32 (*)()} & external ANSI~C function (or C-interoperable Fortran-2003 function) responsible for dispatching the execution among calculation modules. Note that the calculation modules can be implemented in any language that is interoperable with ANSI~C. \\
\hline
{\tt filenm} & {\it char*} & name of sequential {\sc ascii} file containing the CLE-2000 source file, without the {\tt .c2m} suffix. Can be set to {\tt " "} (corresponding to {\tt stdin} in ANSI~C, or unit~5 in Fortran). The name is null terminated. \\
\hline
{\tt iprint} & {\it int\_32} & print parameter (set to zero for no print). \\
\hline
{\tt my\_param} & {\it lifo*} & last-in-first-out (lifo) stack containing LCM (or XSM) objects, files and/or CLE-2000 variables that are exchanged with the CLE-2000 procedure. Set {\tt my\_param = NULL} if  no information is exchanged. The specification of {\tt my\_param} is detailed in Sect.~\ref{sect:lifo}. \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it int\_32} & error code equal to zero if the execution of the CLE-2000 source file is successful. Equal to the error code otherwise. \\
\hline
\end{tabular}

\subsubsection{dummod\index{dummod}}

Function {\tt dummod()} is an external ANSI~C function (or C-interoperable Fortran-2003 function) responsible for dispatching the execution among calculation modules.
A specific version, named {\tt ganmod()}, is used to dispatch the execution among the modules of the GANLIB. Its specifications are:
\begin{verbatim}

dummod(cmodul, nentry, hentry, ientry, jentry, kentry, hparam);
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt cmodul} & {\it char*} & name of the calculation module to execute \\
\hline
{\tt nentry} & {\it int\_32} & number of parameters (LCM objects or files) for this call \\
\hline
{\tt hentry} & {\it char (*)[13]} & names of the parameters as known in the CLE-2000 procedure\\
\hline
{\tt ientry}  & {\it int\_32*} & types of the parameters. $=1$: memory-resident LCM object; $=2$: persistent LCM object (stored in a XSM file); 
$=3$: sequential binary file;
$=4$: sequential ascii file;
$=5$: direct access file;
$=6$: HDF5 file. \\
\hline
{\tt jentry}  & {\it int\_32*} & access mode of the parameters. $=0$: the object is created; $=1$: the object is opened for modifications ; $=2$: the object is opened in read-only mode. \\
\hline
{\tt kentry}  & {\it lcm**} & equal to the address of the LCM object corresponding to a parameter or set to {\tt NULL} if the parameter is a file \\
\hline
{\tt hparam}  & {\it char (*)[73]} &names of the parameters as known by the operating system  \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it int\_32} & error code equal to zero if the execution of {\tt dummod()} is successful. Equal to the error code otherwise. \\
\hline
\end{tabular}

\subsubsection {Calling a main CLE-2000 procedure}

The simplest situation occurs when a main CLE-2000 procedure is called. This situation corresponds to the case where an application
software is run in stand-alone mode. In this case, it is sufficient to write a main program calling a main CLE-2000 procedure. The main
program can be written in ANSI~C (as in the following example) or as a C-interoperable Fortran-2003 program. A main CLE-2000 procedure
has no in-out CLE-2000 variables and no in-out parameters.

\vskip 0.08cm

In the following example, an application software contains three modules, named {\tt MOD1:}, {\tt MOD2} and {\tt MOD3}, respectively.
A main program is simply written as

\begin{verbatim}
#include <string.h>
#include "cle2000.h"
main()
{
   int_32 iprint = 0;
   int_32 ier, ilevel = 1;
   int_32 ganmod();

   ier = cle2000_c(ilevel, &ganmod, " ", iprint, NULL);
   printf("end of execution; ier=%d\n", ier);
}
\end{verbatim}

The {\tt ganmod()} function is another developer-supplied function that is responsible for dispatching the execution among modules
{\tt MOD1:}, {\tt MOD2} or {\tt MOD3}. The {\tt ganmod()} function is responsible for opening any file that can be requested
by these modules. This open/close operation may be different, depending if the modules are programmed in ANSI~C (as in this example) or in another language.
\begin{verbatim}
#include <string.h>
#include <stdio.h>
#include "cle2000.h"
int_32 ganmod(char *cmodul, int_32 nentry, char (*hentry)[13], int_32 *ientry,
       int_32 *jentry, lcm **kentry, char (*hparam)[73])
{
    int_32 iloop1, ier;
    FILE *kentry_file[maxent];
    char hsmg[132];

/* open files */
    for (iloop1 = 0; iloop1 < nentry; ++iloop1) {
        if (ientry[iloop1] >= 3) {
            char *mode;
            if ((ientry[iloop1] == 3) && (jentry[iloop1] == 0)) {
                strcpy(mode, "w");
            } else if ((ientry[iloop1] == 3) && (jentry[iloop1] == 1)) {
                strcpy(mode, "a");
            } else if ((ientry[iloop1] == 3) && (jentry[iloop1] == 2)) {
                strcpy(mode, "r");
            } else if ((ientry[iloop1] == 4) && (jentry[iloop1] == 0)) {
                strcpy(mode, "wb");
            } else if ((ientry[iloop1] == 4) && (jentry[iloop1] == 1)) {
                strcpy(mode, "ab");
            } else if ((ientry[iloop1] == 4) && (jentry[iloop1] == 2)) {
                strcpy(mode, "rb");
            } else {
                sprintf(hsmg, "ganmod: type not supported for file %s", hentry[iloop1]);
                xabort_c(hsmg);
            }
            kentry_file[iloop1] = fopen(hparam[iloop1], mode);
            if (kentry_file[iloop1] == NULL) {
                sprintf(hsmg, "ganmod: unable to open file %s", hentry[iloop1]);
                xabort_c(hsmg);
            }
        } else {
           kentry_file[iloop1] = NULL;
        }
    }
 
/* call modules */
    if(strcmp(cmodul, "MOD1:") == 0) {
        mod1(nentry, hentry, ientry, jentry, kentry, kentry_file);
    } else if(strcmp(cmodul, "MOD2:") == 0) {
        mod2(nentry, hentry, ientry, jentry, kentry, kentry_file);
    } else if(strcmp(cmodul, "MOD3:") == 0) {
        mod3(nentry, hentry, ientry, jentry, kentry, kentry_file);
    } else {
        return 1;
    }

/* close files */
    for (iloop1 = 0; iloop1 < nentry; ++iloop1) {
        if (ientry[iloop1] >= 3) {
            ier = fclose(kentry_file[iloop1]);
            if (ier != 0) {
                sprintf(hsmg, "ganmod: unable to close file %s", hentry[iloop1]);
                xabort_c(hsmg);
            }
        }
    }
    return 0;
}
\end{verbatim}

\subsubsection {Calling a parametrized CLE-2000 procedure}

In cases where an application software is called from a multi-physics application, it is likely that the multi-physics application
will need to call parametrized CLE-2000 procedures (with ``{\tt .c2m}" suffix). This approach provides an efficient way of communication between
the application software and the multi-physics application. It also permit to develop computational schemes outside the scope (i.e., independently)
of the multi-physics application. Parameters are either LCM objects (memory-resident) or
files that are managed by the operating system. Multi-physics applications are generally programmed
in C++ or in Java. In the latter case, {\sl Java Native Interfaces} (JNIs) are required to allow this communication.

\vskip 0.08cm

In the following example, a parametrized procedure, {\tt TESTproc.c2m}, take two object parameters and three CLE-2000 input variables.
Note that the CLE-2000 variables are always defined after LCM and file objects. The first parameter, {\tt MACRO\_ASCII}, is
an {\sc ascii} file written by the procedure and containing an export of the information pointed by the second parameter {\tt MACRO}. This second parameter is a
memory resident LCM object containing a Macrolib. It is accessed in {\tt read-only} mode. The procedure also prints a table-of-content
of the root directory of {\tt MACRO}, using the {\tt UTL:} module of the GANLIB. The procedure {\tt TESTproc.c2m} is implemented as
\begin{verbatim}
REAL KEFF1 KEFF2 ;
INTEGER I123 ;
PARAMETER MACRO_ASCII MACRO ::
    EDIT 1
    ::: SEQ_ASCII MACRO_ASCII ;
    ::: LINKED_LIST MACRO ;
;
:: >>KEFF1<< >>KEFF2<< >>I123<< ;
MODULE UTL: END: ;
*
UTL: MACRO :: DIR ;
MACRO_ASCII := MACRO ;
ECHO "KEFF1=" KEFF1 ""KEFF2=" KEFF2 "I123=" I123 ;
ECHO "procedure TESTproc completed" ;
END: ;
QUIT "XREF" .
\end{verbatim}

\noindent More information about the development of CLE-2000 procedures can be found in Ref.~\citen{cle2000}.

\vskip 0.08cm

The next ANSI~C function is an example of how a multi-physics application can call such a procedure. A LCM object
containing a Macrolib is first created by importing its information from an existing {\sc ascii} file named {\tt Macrolib}. Next, a call to function
{\tt cle2000\_c()} is performed to execute {\tt TESTproc.c2m}. The corresponding {\tt main} program is written
\goodbreak

\begin{verbatim}
#include <string.h>
#include <stdlib.h>
#include "cle2000.h"
main()
{
   int_32 iprint = 0;
   int_32 ier, ilevel = 1;
   FILE *filein;
   char cproce[13];
   int_32 ganmod();
   lcm *my_lcm;
   lifo *my_lifo;
   lifo_node *my_node;
    
/* create the LCM object containing a Macrolib */
   filein = fopen("Macrolib", "r");
   lcmop_c(&my_lcm, "MACRO1", 0, 1, iprint);
   lcmexp_c(&my_lcm, iprint, filein, 2, 2);
   fclose(filein);
   lcmlib_c(&my_lcm);
   lcmcl_c(&my_lcm, 1);
    
/* construct the lifo stack */
   cleopn(&my_lifo);
   /* node 1 */
   my_node = (lifo_node *) malloc(sizeof(lifo_node));
   strcpy(my_node->name, "MACRO_ASCII1"); strcpy(my_node->OSname, "my_ascii_file");
   my_node->type = -6;
   clepush(&my_lifo, my_node);
   /* node 2 */
   my_node = (lifo_node *) malloc(sizeof(lifo_node));
   strcpy(my_node->name, "MACRO1"); strcpy(my_node->OSname, "MACRO1"); my_node->type = 3;
   my_node->value.mylcm = my_lcm;
   clepush(&my_lifo, my_node);
   /* node 3 */
   my_node = (lifo_node *) malloc(sizeof(lifo_node));
   strcpy(my_node->name, "value1"); my_node->type = 12; my_node->value.fval = 1.703945;
   clepush(&my_lifo, my_node);
   /* node 4 */
   my_node = (lifo_node *) malloc(sizeof(lifo_node));
   strcpy(my_node->name, "value2"); my_node->type = 12; my_node->value.fval = 1.562276;
   clepush(&my_lifo, my_node);
   /* node 5 */
   my_node = (lifo_node *) malloc(sizeof(lifo_node));
   strcpy(my_node->name, "value3"); my_node->type = 11; my_node->value.ival = 12345;
   clepush(&my_lifo, my_node);
 
/* call the parametrized procedure */
   strcpy(cproce, "TESTproc");
   ier = cle2000_c(ilevel, &ganmod, cproce, iprint, my_lifo);
   if (ier != 0) xabort_c("example2.1.5: cle2000 failure");

/* erase the lifo stack */
   while (my_lifo->nup > 0) {
      my_node = clepop(&my_lifo);
      free(my_node);
   }
   clecls(&my_lifo);
   printf("successful end of execution\n");
}
\end{verbatim}

\subsubsection {Calling a CLE-2000 procedure with in-out CLE-2000 variables}

The CLE-2000 API also offers the possibility to exchange CLE-2000 variables with a procedure. The following CLE-2000 procedure
permits to compute the factorial of a number, as proposed in Ref.~\citen{cle2000}. Here, {\tt n} and {\tt n\_fact} are input and
output CLE-2000 variable, respectively. The {\tt fact.c2m} procedure is written
\begin{verbatim}
!
! Example of a recursive procedure.
!
!  input  to  "fact": *n*
! output from "fact": *n_fact*
!
 INTEGER   n n_fact prev_fact ;
  ::  >>n<< ;
 IF n 1 = THEN
   EVALUATE n_fact := 1 ;
 ELSE
   EVALUATE n := n 1 - ;
   ! Here, "fact" calls itself
   PROCEDURE fact ;
   fact ::   <<n>>  >>prev_fact<< ;
   EVALUATE n_fact := n 1 + prev_fact * ;
 ENDIF ;
  :: <<n_fact>> ;
 QUIT " Recursive procedure *fact* XREF " .
\end{verbatim}

This procedure can be called from a program implemented in ANSI~C, using
\begin{verbatim}
#include <string.h>
#include <stdlib.h>
#include "cle2000.h"
main()
{
   int_32 iprint = 0;
   int_32 ier, ilevel = 1;
   char cproce[13];
   int_32 ganmod();
   lifo *my_lifo;
   lifo_node *my_node;

/* construct the lifo stack */
   cleopn(&my_lifo);
   /* node 1 */
   my_node = (lifo_node *) malloc(sizeof(lifo_node));
   strcpy(my_node->name, "input_val"); my_node->type = 11; my_node->value.ival = 5;
   clepush(&my_lifo, my_node);
   /* node 2 */
   my_node = (lifo_node *) malloc(sizeof(lifo_node));
   strcpy(my_node->name, "output_val"); my_node->type = -11;
   clepush(&my_lifo, my_node);

/* call the procedure with in-out CLE-2000 variables*/
   strcpy(cproce, "fact");
   ier = cle2000_c(ilevel, &ganmod, cproce, iprint, my_lifo);
   if (ier != 0) xabort_c("fact: cle2000 failure");

/* recover and erase the lifo stack */
   printf("\noutput stack:\n");
   while (my_lifo->nup > 0) {
      my_node = clepop(&my_lifo);
      printf("node %d (name=%12s) ---> %d\n", my_lifo->nup, my_node->name,
         my_node->value.ival);
      free(my_node);
   }
   clecls(&my_lifo);
   printf("successful end of execution\n");
}
\end{verbatim}

\subsection {Calling a calculation module without a CLE-2000 procedure}

The GANLIB API also provides the possibility to call directly a calculation module without a CLE-2000 procedure. This
capability is required in the first-generation Jargon framework, as presented in Ref.~\citen{jargon}. The actual implementation
does not support CLE-2000 variables. A calculation module with ``{\tt >>~<<}" variables must therefore be encapsulated in a
CLE-2000 procedure.

\subsubsection{clemod\_c\index{clemod\_c}}

The general specification of function {\tt clemod\_c()} is

\begin{verbatim}

clemod_c(cmodul, filein, nentry, hentry, ientry, jentry, kentry, hparam, dummod);    
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt cmodul} & {\it char*} & name of the calculation module to execute \\
\hline
{\tt filein} & {\it FILE*} & sequential {\sc ascii} file containing the data for module {\tt cmodul} (i.e., the data between the ``{\tt ::}" and the ``{\tt ;}"). Can be set to {\tt stdin} (standard input, or unit~5 in Fortran) \\
\hline
{\tt nentry} & {\it int\_32} & number of parameters (LCM objects or files) that are exchanged with the CLE-2000 procedure. {\tt nentry = 0} if  no parameters are exchanged. \\
\hline
{\tt hentry} & {\it char (*)[13]} & names of these parameters, as known by the calculation module. Each name is a character string with a maximum of 12 characters. \\
\hline
{\tt ientry} & {\it int\_32*} & types of each parameter. $=1$: memory-resident LCM object; $=2$: persistent LCM object (stored in a XSM file); 
$=3$: sequential binary file;
$=4$: sequential ascii file;
$=5$: direct access file;
$=6$: HDF5 file.
\\
\hline
{\tt jentry} & {\it int\_32*} & mode of each parameter. $=0$: the object is created; $=1$: the object is opened for modifications ; $=2$: the object is opened in read-only mode. \\
\hline
{\tt kentry} & {\it lcm**} & addresses of the {\tt lcm} objects (for parameters that are LCM objects). Set to {\tt NULL} for parameters that are files. \\
\hline
{\tt hparam} & {\it char (*)[73]} & names of these parameters, as known by the operating system. Each name is a character string with a maximum of 72 characters. \\
\hline
{\tt dummod} & {\it int\_32 (*)()} & external ANSI~C function (or C-interoperable Fortran-2003 function) responsible for dispatching the execution among calculation modules. Note that the calculation modules can be implemented in any language that is interoperable with ANSI~C. \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it int\_32} & error code equal to zero if the execution of the calculation module is successful. Equal to the error code otherwise. \\
\hline
\end{tabular}

\vskip 0.8cm

In the following example, function {\tt clemod\_c()} is used to call a calculation module of the GANLIB. A LCM object
containing a Macrolib is first created by importing its information from an existing {\sc ascii} file named {\tt Macrolib}.
Module {\tt UTL:} is called with this {\tt read-only} Macrolib as unique parameter:
\begin{verbatim}
#include <string.h>
#include "cle2000.h"
#define maxent 64  /* maximum number of module arguments */
main()
{
    int_32 ganmod();
    char hentry[maxent][13], hparam[maxent][73];
    int_32 ier, nentry, ientry[maxent], jentry[maxent];
    lcm * my_lcm, *kentry[maxent];
    FILE *filein;
    
/* create the LCM object containing a Macrolib */
    filein = fopen("Macrolib", "r");
    lcmop_c(&my_lcm, "MACRO", 0, 1, 99);
    lcmexp_c(&my_lcm, 99, filein, 2, 2);
    fclose(filein);
 
/* create a file containing the UTL: data */
    filein = fopen("UTLdata", "r");

/* construct the parameter */
    nentry = 1 ;
    strcpy(hentry[0], "MACRO"); strcpy(hparam[0], "MACRO"); ientry[0]=1; jentry[0]=2;
    kentry[0]=my_lcm;
 
/* execute the module */
    ier = clemod_c("UTL:", filein, nentry, hentry, ientry, jentry, kentry, hparam,
          &ganmod);    
    lcmcl_c(&my_lcm, 1);
    fclose(filein);
    printf("end of execution; ier=%d\n", ier);
}
\end{verbatim}

\vskip 0.08cm

The ASCII file {\tt UTLdata} contains the data for module {\tt UTL:}. Here, it is defined as
\begin{verbatim}
DIR STEP UP GROUP
STEP AT 1 DIR STEP DOWN
STEP DOWN ;
\end{verbatim}

\subsection{Management of the last-in-first-out (lifo) stack\index{lifo}}\label{sect:lifo}

A last-in-first-out (lifo) stack manage the stored data so that the last data stored in the stack is the first data removed from the stack. This means that a POP function retrieves the values most recently stored with a PUSH function. CLE-2000 uses one lifo stack to manage information used within each specific CLE-2000 procedure instance and one lifo stack as dummy parameter list each time a CLE-2000 procedure is called.

\vskip 0.08cm

In case where a CLE-2000 procedure is called from a multi-physics environment, the parameter information is first integrated in a lifo stack {\sl before} calling
function {\tt cle2000\_c()}. After execution of the procedure, output parameter information is recovered from the lifo stack. The lifo stack can contain LCM (or XSM) objects, files and/or CLE-2000 variables. The lifo stack is constructed as a linked list of nodes, each node containing a single parameter. Three important rules must be satisfied:
\begin{itemize}
\item LCM (or XSM) objects and files must be defined prior to CLE-2000 variables in the lifo stack used as parameter information.
\item LCM (or XSM) objects and files must be closed when included in the lifo stack.
\item Output nodes are also included in the lifo stack before calling function {\tt cle2000\_c()}, but {\sl with negative} {\tt type} component and {\sl without} {\tt value} component.
\end{itemize}

\vskip 0.08cm

The specification of a lifo node is:

\small
\begin{verbatim}
typedef struct LIFO_NODE {     /* node in last-in-first-out (lifo) stack */
   int_32 type;                /* type of node: 3= lcm object; 4= xsm file; 5= seq binary;
                                  6= seq ascii; 7= da binary; 8= hdf5 file; 11= integer value;
                                  12= real value; 13= character string; 14= double precision value;
                                  15= logical value */
   int_32 access;              /* 0=creation mode/1=modification mode/2=read-only mode */
   int_32 lparam;              /* record length for DA file objects */
   union {
       int_32 ival;            /* integer or logical value */
       float_32 fval;          /* real value */
       double dval;            /* double precision value */
       lcm *mylcm;             /* handle towards a LCM object */
       char hval[73];          /* character value */
       hid_t myhdf5;           /* handle towards a HDF5 file */
   } value;
   struct LIFO_NODE *daughter; /* address of the daughter node in stack */
   char name[13];              /* name of node in the calling script */
   char name_daughter[13];     /* name of node in the daughter script */
   char OSname[73];            /* physical filename */
} lifo_node ;
\end{verbatim}
\normalsize

\vskip 0.8cm

\noindent
\begin{tabular}{|p{2.4cm}|p{1.6cm}|p{10.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf life\_node components:} \\
\hline
{\tt type} & {\it int\_32} & type of data in node.
$=\pm 3$: LCM object;
$=\pm 4$: XSM file;
$=\pm 5$: sequential binary file;
$=\pm 6$: sequential ascii file;
$=\pm 7$: direct access binary file;
$=\pm 8$: HDF5 file;
$=\pm 11$: integer CLE-2000 value;
$=\pm 12$: real CLE-2000 value;
$=\pm 13$: character string (null-terminated);
$=\pm 14$: double precision CLE-2000 value;
$=\pm 15$: logical CLE-2000 value.
A positive value indicates that an input value is provided; a negative value indicates that {\sl no} input value is provided
so that the node is {\sl empty}. Empty nodes are defined to receive calculational results.
\\
\hline
{\tt access} & {\it int\_32} & access state of data in node. 
$= 0$: creation mode;
$= 1$: modification mode;
$= 2$: read-only mode.
This information is used internally in {\tt cle2000\_c()} function.
\\
\hline
{\tt lparam} & {\it int\_32} & record length (in bytes) for DA file objects.  This data is given if and only if $|${\tt type}$| = 7$.\\
\hline
{\tt value.ival} & {\it int\_32} & integer or logical CLE-2000 value. This data is given or is available at output if and only if {\tt type} $= 11$ or $=15$.\\
\hline
{\tt value.fval} & {\it float\_32} & real CLE-2000 value. This data is given or is available at output if and only if {\tt type} $= 12$.\\
\hline
{\tt value.hval} & {\it char[73]} & character string CLE-2000 value. This data is given or is available at output if and only if {\tt type} $= 13$.\\
\hline
{\tt value.dval} & {\it double} & double precision CLE-2000 value. This data is given or is available at output if and only if {\tt type} $= 14$.\\
\hline
{\tt value.mylcm} & {\it lcm*} & LCM object (memory-resident). This data is given or is available at output if and only if {\tt type} $= 3$. The LCM object is closed.\\
\hline
{\tt daughter} & {\it lifo\_node*} & address of the daughter node in stack. This information is used by the lifo utility to construct the linked list of nodes.\\
\hline
{\tt name} & {\it char[13]} & name of node in the calling script.\\
\hline
{\tt name\_daughter} & {\it char[13]} & name of node in the daughter script. This name is used internally in {\tt cle2000\_c()} function.\\
\hline
{\tt OSname} & {\it char[73]} & name of node as known by the operating system. In the case of a LCM object, it is the name given to {\tt lcmop\_c()} function. In the case of a file, it is the operating system name of the file. The LCM object or file is closed. {\bf This data is given if and only if} $|${\tt type}$| \le 10$.\\
\hline
\end{tabular}

\vskip 1.0cm

The following functions are used to manage the lifo stack.

\vskip 0.8cm
\goodbreak

\subsubsection {cleopn\index{cleopn}}

Create an empty lifo stack.

\begin{verbatim}

cleopn(my_lifo);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt my\_lifo} & {\it lifo**} & address of the empty lifo stack. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{clepop\index{clepop}}

Remove the ``last-in" node from the lifo stack.

\begin{verbatim}

clepop(my_lifo);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt my\_lifo} & {\it lifo**} & address of the lifo stack. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it lifo\_node*} & node removed from the lifo stack \\
\hline
\end{tabular}

\subsubsection{clepush\index{clepush}}

Add a new node in the lifo stack.

\begin{verbatim}

clepush(my_lifo, my_node);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt my\_lifo} & {\it lifo**} & address of the lifo stack. \\
\hline
{\tt my\_node} & {\it lifo\_node*} & node to add to the lifo stack. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsubsection{clecls\index{clecls}}

Delete an empty lifo stack.

\begin{verbatim}

clecls(my_lifo);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt my\_lifo} & {\it lifo**} & address of the empty lifo stack. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it int\_32} & error code. $=0$: successful; $=-1$: the lifo stack is not empty. \\
\hline
\end{tabular}

\subsubsection{clenode\index{clenode}}

Return the node with name {\tt my\_name}. The lifo stack is not modified.
\begin{verbatim}

clenode(my_lifo, my_name);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt my\_lifo} & {\it lifo**} & address of the lifo stack. \\
\hline
{\tt my\_name} & {\it char*} & name of the node. The name is null-terminated. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it lifo\_node*} & node of name {\tt my\_name} or NULL if the node doesn't exist. \\
\hline
\end{tabular}

\subsubsection{clepos\index{clepos}}
Return the {\tt ipos}--th node in the stack. The lifo stack is not modified.
\begin{verbatim}

clepos(my_lifo, ipos);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt my\_lifo} & {\it lifo**} & address of the lifo stack. \\
\hline
{\tt ipos} & {\it int\_32} & position of the node in the stack. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it lifo\_node*} & {\tt ipos}--th node or NULL if the node doesn't exist. \\
\hline
\end{tabular}

\subsubsection{clelib\index{clelib}}
Print a table-of-content for the lifo stack.
\begin{verbatim}

clelib(my_lifo);
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt my\_lifo} & {\it lifo**} & address of the lifo stack. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsection {The free-format input reader}

The free-format input reader of CLE-2000 is implemented using four functions: {\tt redopn\_c()}, {\tt redget\_c()}, {\tt redput\_c()} and {\tt redcls\_c()}.
Only {\tt redget\_c()} and {\tt redput\_c()} are expected to be used in an application software.

\subsubsection{redopn\_c\index{redopn\_c}}

Function {\tt redopn\_c()} is called to open the input reader.
The general specification of function {\tt redopn\_c()} is

\begin{verbatim}

redopn_c(iinp1, iout1, hout1, nrec);
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt iinp1} & {\it kdi\_file*} & KDI object containing the CLE-2000 input data, as computed  by {\tt clepil()} and {\tt objpil()} functions of CLE-2000.\\
\hline
{\tt iout1} & {\it FILE*} & sequential {\sc ascii} file used to write execution messages. Can be set to {\tt stdout}. \\
\hline
{\tt hout1} & {\it char*} & name of the sequential {\sc ascii} file used to write execution messages. \\
\hline
{\tt nrec} & {\it int\_32} & record index where reading occurs. Can be set to zero at first call. Set to the value returned by {\tt redcls\_c()} at subsequent calls.\\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\subsubsection{redget\_c\index{redget\_c}}

Function {\tt redget\_c()} is called within modules of the application software to recover the module-specific input data.
The general specification of function {\tt redget\_c()} is

\begin{verbatim}

redget_c(ityp, nitma, flott, text, dflot);
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ityp} & {\it int\_32*} & type of the CLE-2000 variable. A negative value indicates that the variable is to be computed by the application software and returned towards CLE-2000 using a call to {\tt redput\_c}. $=\pm 1$: integer type;
$=\pm 2$: real (single precision) type;
$=\pm 3$: string type;
$=\pm 4$: double precision type;
$=\pm 5$: logical type.\\
\hline
{\tt nitma} & {\it int\_32*} & integer input value when {\tt ityp} $= 1$ or $= 5$;  number of characters when {\tt ityp} $= 3$. \\
\hline
{\tt flott} & {\it float\_32*} &  real input value when {\tt ityp} $= 2$.  \\
\hline
{\tt text} & {\it char[73]} & character string input value when {\tt ityp} $= 3$.   \\
\hline
{\tt dflot} & {\it double\_64*} & double precision input value when {\tt ityp} $= 4$.   \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void}  &  \\
\hline
\end{tabular}

\subsubsection{redput\_c\index{redput\_c}}

Function {\tt redput\_c()} is called within modules of the application software to make information computed by the module available as CLE-2000 variables to the CLE-2000 procedure.
The application software must first call {\tt redget\_c()} and obtain a negative value of {\tt ityp}. A call to {\tt redput\_c()} is next performed with its first parameter set to
$-${\tt ityp} (now, a positive value) and with the corresponding value of the parameter.
The general specification of function {\tt redput\_c()} is

\begin{verbatim}

redput_c(ityp, nitma, flott, text, dflot);
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ityp} & {\it int\_32*} & type of the CLE-2000 variable. $=1$: integer type;
$=2$: real (single precision) type;
$=3$: string type;
$=4$: double precision type;
$=5$: logical type.\\
\hline
{\tt nitma} & {\it int\_32*} & integer output value when {\tt ityp} $= 1$ or $= 5$;  number of characters when {\tt ityp} $= 3$. \\
\hline
{\tt flott} & {\it float\_32*} &  real output value when {\tt ityp} $= 2$. \\
\hline
{\tt text} & {\it char*} & character string output value when {\tt ityp} $= 3$.  \\
\hline
{\tt dflot} & {\it double\_64*} & double precision output value when {\tt ityp} $= 4$.  \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{4.0cm}|p{11cm}|}
\hline
\multicolumn{2}{|c|}{\bf value of the function:} \\
\hline
{\it void} &  \\
\hline
\end{tabular}

\subsubsection{redcls\_c\index{redcls\_c}}

Function {\tt redcls\_c()} is called to close the input reader.
The general specification of function {\tt redcls\_c()} is

\begin{verbatim}

redcls_c(iinp1, iout1, hout1, nrec)
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt iinp1} & {\it kdi\_file**} & KDI object containing the CLE-2000 input data.\\
\hline
{\tt iout1} & {\it FILE**} & sequential {\sc ascii} file used to write execution messages. \\
\hline
{\tt hout1} & {\it char[73]} & name of the sequential {\sc ascii} file used to write execution messages. \\
\hline
{\tt nrec} & {\it int\_32*} & record index where reading occurs. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\subsection{Defining built-in constants in CLE-2000}

CLE-2000 has pre-defined built-in constants, either with mathematical meaning (e.g., $\pi$) or with physical meaning. Currently, available physical constants are
related to reactor physics. In future, one may want to include more physical constants. Here is the specification of the function available inside CLE-2000 to define these constants.

\subsubsection{clecst\index{clecst}}

Function {\tt dumcst()} is an external ANSI~C function implementing pre-defined parametric constants. A standard version is available in the GANLIB with name {\tt clecst()}. It is specified as
\begin{verbatim}

clecst(cparm, ityp, nitma, flott, text, dflot);
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
cparm & {\it char*} & name of the parametric constant (name starting with \$) \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2cm}|p{11cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ityp} & {\it int\_32*} & type of the parametric constant ($1 \le$ {\tt ityp} $ \le 5$) \\
\hline
{\tt nitma} & {\it int\_32*} & integer value of the parametric constant if {\tt ityp} $= 1$; logical value (=1: true/=-1: false) of the parametric constant if {\tt ityp} $= 5$;
number of characters in the string if {\tt ityp} $= 3$. \\
\hline
{\tt flott} & {\it float\_32*} & real value of the parametric constant if {\tt ityp} $= 2$ \\
\hline
{\tt text} & {\it char*} & character string value of the parametric constant if {\tt ityp} $= 3$ \\
\hline
{\tt dflot} & {\it double\_64*} & double precision value of the parametric constant if {\tt ityp} $= 4$ \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{{\it int\_32}} & error code equal to zero if the execution of {\tt clecst()} is successful. Equal to the error code otherwise. \\
\hline
\end{tabular}

\section {The ISO Fortran {\sc lcm} API}

The ISO Fortran {\sc lcm} API is a set of Fortran-2003 wrapper subroutines or functions programmed around the ANSI-C functions of the {\sc lcm} API. This implementation is using
the C interoperability capabilities normalized by ISO and available in the Fortran-2003 compilers. All the subroutines and functions presented in this section are ISO-standard and 64-bit clean.

\vskip 0.08cm

Each LCM object has a {\sl root associative table} from which the complete object is constructed.

\vskip 0.08cm

Any subroutines or functions using the Fortran {\sc lcm} API must include a {\tt USE} statement of the form
\begin{verbatim}
USE GANLIB
\end{verbatim}

The address of a LCM object is a {\tt TYPE(C\_PTR)} variable declared as
\begin{verbatim}
      TYPE(C_PTR) :: IPLIST
\end{verbatim}
\noindent This intrinsic type is defined by the {\tt USE GANLIB} statement. Very few operations are permitted on
{\tt C\_PTR} variables. A {\tt C\_PTR} variable can be nullified by writing
\begin{verbatim}
      IPLIST=C_NULL_PTR
\end{verbatim}
\noindent and a {\tt C\_PTR} variable can be checked for association with actual data using
\begin{verbatim}
      IF(C_ASSOCIATED(IPLIST)) THEN
\end{verbatim}

\subsection{Opening, closing and validation of LCM objects}

\subsubsection{LCMOP\index{LCMOP}}

Open an LCM object (either memory resident or persistent). Obtain the address of the LCM
object if it is created. Note that CLE-2000 is responsible to perform the calls to {\tt LCMOP} for the LCM
objects that are used as parameters of a CLE-2000 module. The use
of {\tt LCMOP} is generally restricted to the use of temporary LCM objects created within a CLE-2000 module.
\begin{verbatim}

CALL LCMOP(IPLIST,NAMP,IMP,MEDIUM,IMPX)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the LCM object if {\tt IMP=1} or {\tt imp=2}. {\tt IPLIST} corresponds to the address of the root associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*72} & name of the LCM object if  {\tt IMP=0}. \\
\hline
{\tt IMP} & {\it INTEGER} & =0 to create a new LCM object ; 
                                  =1 to modify an existing LCM object; 
				  =2 to access an existing LCM object in {\bf read-only} mode. \\
\hline
{\tt MEDIUM} & {\it INTEGER} & =1 to use a memory-resident LCM object; 
                                     =2 to use an {\sc xsm} file to store the LCM object. \\
\hline
{\tt IMPX} & {\it INTEGER} & print parameter. Equal to zero to suppress all printings. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of an LCM object if  {\tt IMP=0}. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the LCM object if {\tt IMP=1} or {\tt IMP=2}. \\
\hline
\end{tabular}

\subsubsection{LCMCL\index{LCMCL}}

Close an LCM object (either memory resident or persistent). Note that CLE-2000 is responsible to perform the calls to
{\tt LCMCL} for the LCM objects that are used as parameters of a CLE-2000 module. The use
of {\tt LCMCL} is generally restricted to the use of temporary LCM objects created within a CLE-2000 module.

\vskip 0.2cm

A LCM object can only be closed if {\tt IPLIST} points towards its root directory.

\begin{verbatim}

CALL LCMCL(IPLIST,IACT)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the LCM object (address of the root directory of the LCM object). \\
\hline
{\tt IACT} & {\it INTEGER} & =1 close the LCM object without destroying it; =2 and destroying it  \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & {\tt IPLIST=0} indicates that the LCM object is closed and destroyed. A memory-resident LCM object keeps the
same address during its complete existence. A persistent LCM object is associated to an XSM file and is represented by a different
value of {\tt IPLIST} each time it is reopened. \\
\hline
\end{tabular}

\subsubsection{LCMVAL\index{LCMVAL}}

Subroutine to validate a single block of data in a LCM object or the totality of the LCM object,
starting from the address of an associative table. This function has no effect if the object is
persistent. The validation consists to verify the connections between the elements of the LCM
object, to verify that each element of the object is defined and to check for possible memory corruptions.
If an error is detected, the following message is issued:

\begin{verbatim}
LCMVAL: BLOCK xxx OF THE TABLE yyy HAS BEEN OVERWRITTEN.
\end{verbatim}

This function is called as

\begin{verbatim}

CALL LCMVAL(IPLIST,NAMP)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table or of the heterogeneous list. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the block to validate in the associative table. 
If {\tt NAMP='~'}, all the blocks in the associative table are verified in a recursive way. \\
\hline
\end{tabular}

\subsection{Interrogation of LCM objects}

The data structures in an LCM object are self-described. It is therefore possible to
interrogate them in order to know their characteristics.

\vskip 0.4cm

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{type of interrogation} \\
\cline{3-4}
\multicolumn{2}{c|}{} & father structure~~~~  & information block \\
\hline
father & associative table & {\tt LCMINF} & {\tt LCMLEN} \\
       &                   & {\tt LCMNXT} &              \\
\cline{2-4}
       & heterogeneous list  & {\tt LCMINF} & {\tt LCMLEL} \\
\hline
\end{tabular}
\end{center}

\subsubsection{LCMLEN\index{LCMLEN}}

Subroutine used to recover the length and type of an information block stored in an
associative table (either memory-resident or persistent). The length is the number of
elements in a daughter heterogeneous list or the number of elements in an array of elementary type.
If {\tt itylcm=3}, the length is the number of {\tt character*4} words. As an example, the length required
to store an array of {\tt character*8} words is twice its dimension.

\begin{verbatim}

CALL LCMLEN(IPLIST,NAMP,ILONG,ITYLCM)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the block. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ILONG} & {\it INTEGER} & length of the block. =$-1$ for a daughter associative table; 
                                    =$N$ for a daughter heterogeneous list containing $N$ components; 
		                 =0 if the block does't exist.\\
\hline
{\tt ITYLCM} & {\it INTEGER} & type of information. =0 associative table; =1 32-bit integer; 
                                    =2 32-bit real; =3 {\tt character*4} data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =10 heterogeneous list; 
				    =99 undefined (99 is returned if the block does't exist). \\
\hline
\end{tabular}

\subsubsection{LCMINF\index{LCMINF}}

Subroutine used to recover general information about a LCM object.

\begin{verbatim}

CALL LCMINF(IPLIST,NAMLCM,NAMMY,EMPTY,ILONG,LCM)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table or of the heterogeneous list. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt NAMLCM} & {\it CHARACTER*72} & name of the LCM object. \\
\hline
{\tt NAMMY} & {\it CHARACTER*12} & name of the associative table at address {\tt IPLIST}. $=${\tt '/'} if the associative table
is the root of the LCM object; $=${\tt ' '} if the associative table
is an heterogeneous list component. 
\\
\hline
{\tt EMPTY} & {\it LOGICAL} & logical variable set to {\tt .true.} 
                            if the associative table is empty
			    or set to {\tt .false.} otherwise. \\
\hline
{\tt ILONG} & {\it INTEGER} & $=-1$: {\tt IPLIST} is an associative table; $>0$: number of components in the heterogeneous list  {\tt IPLIST}\\
\hline
{\tt LCM} & {\it LOGICAL} & logical variable set to {\tt .true.} 
                                  if information is memory-resident or set to {\tt .false.} if information is persistent (stored in an XSM file). \\
\hline
\end{tabular}

\subsubsection{LCMNXT\index{LCMNXT}}

Subroutine used to find the name of the next block of data in an associative table. Use
of {\tt LCMNXT} is forbidden if the associative table is empty. The order of names is
arbitrary. The search cycle indefinitely.

\begin{verbatim}

CALL LCMNXT(IPLIST,NAMP)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} &  name of an existing block.
                                   {\tt NAMP=' '} can be used to obtain a first name to initiate the search. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the next block. 
A call to {\tt XABORT} is performed if the associative table is empty. \\
\hline
\end{tabular}

\subsubsection{LCMLEL\index{LCMLEL}}

Subroutine used to recover the length and type of an information block stored in an
heterogeneous list (either memory-resident or persistent). The length is the number of
elements in a daughter heterogeneous list or the number of elements in an array of elementary type.
If {\tt itylcm=3}, the length is the number of {\tt character*4} words. As an example, the length required
to store an array of {\tt character*8} words is twice its dimension.

\begin{verbatim}

CALL LCMLEL(IPLIST,ISET,ILONG,ITYLCM)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the block in the list.
The first element of the list is located at index $1$.\\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ILONG} & {\it INTEGER} & length of the block. =0 if the block does't exist. \\
\hline
{\tt ITYLCM} & {\it INTEGER} & type of information. =0 associative table; =1 32-bit integer; 
                                    =2 32-bit real; =3 {\tt character*4} data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =10 heterogeneous list; 
				    =99 undefined (99 is returned if the block does't exist). \\
\hline
\end{tabular}

\subsection{Management of the array of elementary type}

Management of the array of elementary type can be performed {\sl with} copy of the data ({\tt LCMPUT}, {\tt LCMGET}, {\tt LCMPDL} or
{\tt LCMGDL}) or {\sl without} copy ({\tt LCMPPD}, {\tt LCMGPD}, {\tt LCMPPL} or {\tt LCMGPL}).

\vskip 0.4cm

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{type of operation} \\
\cline{3-4}
\multicolumn{2}{c|}{} & put~~~~~~~~~~~~~ & get~~~~~~~~~~~~~ \\
\hline
father & associative table & {\tt LCMPUT} & {\tt LCMGET} \\
       &                   & {\tt LCMPPD} & {\tt LCMGPD} \\
\cline{2-4}
       & heterogeneous list & {\tt LCMPDL} & {\tt LCMGDL} \\
       &                   & {\tt LCMPPL} & {\tt LCMGPL} \\
\hline
\end{tabular}
\end{center}

\subsubsection{LCMGET\index{LCMGET}}

Subroutine used to recover an information block (array of elementary type) from an associative table and to copy
this data into memory.

\begin{verbatim}

CALL LCMGET(IPLIST,NAMP,DATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} &  name of the block to recover. 
                                    A call to {\tt XABORT} is performed if the block does't exist. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt DATA} & {\it CLASS(*)} & array of dimension $\ge$ {\tt ILONG} in which the block is copied. \\
\hline
\end{tabular}

\vskip 0.4cm

Subroutine {\tt LCMGET} can be used to recover character-string information available in a block
of the LCM object. It is also possible to use subroutine {\tt LCMGCD} presented in \Sect{LCMGCD}.
In the following example, a block is stored in an associative table located at
address {\tt IPLIST}. The block has a name {\tt NAMP} and a length equivalent to 5 32-bit words.
The information is recovered into the integer array {\tt IDATA} and transformed into a {\tt character*20} variable named {\tt HNAME} using an internal {\tt WRITE} statement:

\begin{verbatim}
      USE GANLIB
      ...
      CHARACTER NAMP*12,HNAME*20
      INTEGER IDATA(5)
      TYPE(C_PTR) IPLIST
      ...
      IPLIST=...
      NAMP=...
      CALL LCMGET(IPLIST,NAMP,IDATA)
      WRITE(HNAME,'(5A4)') (IDATA(I),I=1,5)
\end{verbatim}

\subsubsection{LCMPUT\index{LCMPUT}}

Subroutine used to store a block of data (array of elementary type) into an associative table. 
The information is copied from memory towards the LCM object. If the block already exists, it is replaced;
otherwise, it is created. This operation cannot be performed into a LCM object open in {\tt read-only} mode.

\begin{verbatim}

CALL LCMPUT(IPLIST,NAMP,ILONG,ITYLCM,DATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the block. \\
\hline
{\tt ILONG} & {\it INTEGER} & length of the block. If the array contains $N$ {\tt character*8} words, 
                                   {\tt ilong} must be set to $2 \times N$. \\
\hline
{\tt ITYLCM} & {\it INTEGER} & type of information. =1 32-bit integer; 
                                    =2 32-bit real; =3 {\tt character*4} data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =99 undefined. \\
\hline
{\tt DATA} & {\it CLASS(*)} & array of dimension $\ge$ {\tt ILONG} to be copied into the LCM object. 
                                   Array elements {\tt DATA} must be initialized before the call to {\tt LCMPUT}. \\
\hline
\end{tabular}

\vskip 0.4cm

Subroutine {\tt LCMPUT} can be used to store character-string information in an associative table of a LCM object.
It is also possible to use function {\tt LCMPCD} presented in \Sect{LCMPCD}. In the
following example, a character string {\tt HNAME} is first transformed into an integer array {\tt IDATA}
using an internal {\tt READ} statement. This array (block of data) is stored into the LCM object located at
address {\tt IPLIST}, using {\tt LCMPUT}. The block has a name {\tt NAMP}, a length equivalent to 5 32-bit words, and a type
equal to 3.

\begin{verbatim}
      USE GANLIB
      ...
      CHARACTER NAMP*12,HNAME*20
      INTEGER IDATA(5)
      TYPE(C_PTR) IPLIST
      ...
      IPLIST=...
      NAMP=...
      READ(HNAME,'(5A4)') (IDATA(I),I=1,5)
      CALL LCMPUT(IPLIST,NAMP,5,3,IDATA)
\end{verbatim}

\subsubsection{LCMGPD\index{LCMGPD}}

Subroutine used to recover the {\tt TYPE(C\_PTR)} address of an information block (array of elementary type) from an associative table,
{\sl without} making a copy of the information. Use of this subroutine must respect the following rules:
\begin{itemize}
\item If the information is modified after the call to {\tt LCMGPD}, a call to {\tt LCMPPD} 
must be performed to acknowledge the modification.
\item The block pointed by {\tt IOFSET} should never be released using a deallocation function such as
{\tt RLSARA}, {\tt deallocate}, etc.
\item The variable {\tt IOFSET} must never be copied into another variable.
\end{itemize}
Non respect of these rules may cause execution failure (core dump,
segmentation fault, etc) without possibility to throw an exception.

\vskip 0.2cm

Subroutine {\tt LCMGPD} implements direct {\sl pinning} on LCM data structures. It represents an advanced capability of the {\sc lcm} API and should only be used in situations where
the economy of computer resources is a critical issue. The {\tt C\_PTR} address is the ANSI~C pointer of a block of
information made available into a Fortran program. If {\tt IOFSET} is a {\tt C\_PTR} address, the useful information is
accessed in a Fortran variable {\tt IDATA} set using
\begin{verbatim}
   USE GANLIB
   ...
   TYPE(C_PTR) :: IOFSET
   INTEGER, POINTER, DIMENSION(:) :: IDATA
   ...
   CALL LCMGPD(IPLIST,NAMP,IOFSET)
   CALL C_F_POINTER(IOFSET,IDATA, (/ ILONG /))
\end{verbatim}

The useful information is therefore accessed in memory locations {\tt IDATA(1)} to {\tt IDATA(ILONG)}.

\vskip 0.2cm

A call to {\tt LCMGPD} doesn't cause any modification to the LCM object.

\vskip 0.5cm

\begin{verbatim}

CALL LCMGPD(IPLIST,NAMP,IOFSET)
\end{verbatim}

\vskip 0.5cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the block to recover.
A call to {\tt XABORT} is performed if the block does't exist. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IOFSET} &  {\it TYPE(C\_PTR)} & {\tt C\_PTR} address of the information. \\
\hline
\end{tabular}

\subsubsection{LCMPPD\index{LCMPPD}}

Subroutine used to store a block of data (array of elementary type) into an associative table
{\sl without} making a copy of the information. If the block already exists, it is replaced;
otherwise, it is created. This operation cannot be performed into a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

{\sl If a block named  {\tt NAMP} already exists in the associative table, the address associated
with {\tt NAMP} is replaced by the new address and the information pointed by the old address
is deallocated.}

\vskip 0.2cm

Subroutine {\tt LCMPPD} implements direct {\sl pinning} on LCM data structures. It represents an advanced capability of the {\sc lcm} API and should only be used in situations where
the economy of computer resources is a critical issue. The memory block stored by {\tt LCMPPD} must be previously
allocated by a call to {\tt LCMARA} of the form
\begin{verbatim}
IOFSET=LCMARA(JLONG)
\end{verbatim}

\noindent where {\tt JLONG} is the number of 32-bit words required to store the memory block. {\tt JLONG} is generally equal to {\tt ILONG} except if
{\tt ITYLCM}=4 or {\tt ITYLCM}=6 where {\tt JLONG}={\tt 2*ILONG}.

\vskip 0.2cm

If {\tt ITYLCM}=1, the useful information is accessed in a Fortran variable {\tt IDATA} set using a {\tt C\_F\_POINTER} function:
\begin{verbatim}
   USE GANLIB
   ...
   TYPE(C_PTR) :: IOFSET
   INTEGER, POINTER, DIMENSION(:) :: IDATA
   ...
   IOFSET = LCMARA(ILONG)
   CALL C_F_POINTER(IOFSET,IDATA, (/ ILONG /))
   ...
   CALL LCMPPD(IPLIST,NAMP,ILONG,ITYLCM,IOFSET)
\end{verbatim}

The useful information is therefore accessed in memory locations {\tt IDATA(1)} to {\tt IDATA(ILONG)}. There is no need to 
declare {\tt LCMARA} as an external function; this declaration is included in the module set by the {\tt USE GANLIB} statement.

\begin{verbatim}

CALL LCMPPD(IPLIST,NAMP,ILONG,ITYLCM,IOFSET)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the block. \\
\hline
{\tt ILONG} & {\it INTEGER} & length of the block. \\
\hline
{\tt ITYLCM} & {\it INTEGER} & type of information. =1 32-bit integer; 
                                    =2 32-bit real; =3 {\tt character*4} data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =99 undefined.\\
\hline
{\tt IOFSET} &  {\it TYPE(C\_PTR)} & {\tt C\_PTR} address of the information. Data elements pointed
by {\tt IOFSET} must be initialized before the call to {\tt LCMPPD}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IOFSET} & {\it TYPE(C\_PTR)}  & {\tt IOFSET=C\_NULL\_PTR} to indicate that the information previously pointed by
                                     {\tt IOFSET} is now managed by {\tt LCM}. \\
\hline
\end{tabular}

\subsubsection{LCMDEL\index{LCMDEL}}

Subroutine used to erase an information block or a daughter heterogeneous list stored in a memory-resident associative table.
Subroutine {\tt LCMDEL} {\sl cannot} be used with persistent LCM objects.

\begin{verbatim}

CALL LCMDEL(IPLIST,NAMP)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the block to erase. \\
\hline
\end{tabular}

\subsubsection{LCMGDL\index{LCMGDL}}

Subroutine used to recover an information block (array of elementary type) from an heterogeneous list and to copy
this data into memory.

\begin{verbatim}

CALL LCMGDL(IPLIST,ISET,DATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the block in the heterogeneous list. A call to {\tt XABORT} 
                                   is performed if the block does't exist.
The first element of the list is located at index $1$.\\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt DATA} & {\it CLASS(*)} & array of dimension $\ge$ {\tt ILONG} in which the block is copied. \\
\hline
\end{tabular}

\vskip 0.4cm

Subroutine {\tt LCMGDL} can be used to recover character-string information available in a block
of the LCM object. It is also possible to use subroutine {\tt LCMGCL} presented in \Sect{LCMGCL}.
In the following example, a block is stored in an heterogeneous list located at
address {\tt IPLIST}. The block is located at the {\tt ISET}--th position of the heterogeneous list and has a length equivalent to 5 32-bit words.
The information is recovered into the integer array {\tt IDATA} and transformed into a {\tt character*20} variable named {\tt HNAME} using an internal {\tt WRITE} statement:

\begin{verbatim}
      USE GANLIB
      ...
      CHARACTER HNAME*20
      INTEGER IDATA(5)
      TYPE(C_PTR) IPLIST
      ...
      IPLIST=...
      ISET=...
      CALL LCMGDL(IPLIST,ISET,IDATA)
      WRITE(HNAME,'(5A4)') (IDATA(I),I=1,5)
\end{verbatim}

\subsubsection{LCMPDL\index{LCMPDL}}

Subroutine used to store a block of data (array of elementary type) into an heterogeneous list. 
The information is copied from memory towards the LCM object. If the block already exists, it is replaced;
otherwise, it is created. This operation cannot be performed into a LCM object open in {\tt read-only} mode.

\begin{verbatim}

CALL LCMPDL(IPLIST,ISET,ILONG,ITYLCM,DATA)
\end{verbatim}

\vskip 0.2cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} &  index of the block in the list.
The first element of the list is located at index $1$.\\
\hline
{\tt ILONG} & {\it INTEGER} &  length of the block. If the array contains $N$ {\tt character*8} words, 
                                   {\tt ILONG} must be set to $2 \times N$ \\
\hline
{\tt ITYLCM} & {\it INTEGER} & type of information. =1 32-bit integer; 
                                    =2 32-bit real; =3 {\tt character*4} data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex; =99 undefined. \\
\hline
{\tt DATA} & {\it CLASS(*)} & array of dimension $\ge$ {\tt ILONG} to be copied into the LCM object. 
                                   Array elements {\tt DATA} must be initialized before the call to {\tt LCMPDL}. \\
\hline
\end{tabular}

\vskip 0.4cm

Subroutine {\tt LCMPDL}  can be used to store character-string information into an heterogeneous list of a LCM object. In the
following example, a character string {\tt HNAME} is first transformed into an integer array {\tt IDATA}
using an internal {\tt READ} statement. This array (block of data) is stored into the LCM object located at
address {\tt IPLIST}, using {\tt LCMPDL} . The block is located at the {\tt ISET}--th position of the heterogeneous list, has a length equivalent to 5 32-bit words, and a type
equal to 3.

\begin{verbatim}
      USE GANLIB
      ...
      CHARACTER HNAME*20
      INTEGER IDATA(5)
      TYPE(C_PTR) IPLIST
      ...
      IPLIST=...
      ISET=...
      READ(HNAME,'(5A4)') (IDATA(I),I=1,5)
      CALL LCMPDL(IPLIST,ISET,5,3,IDATA)
\end{verbatim}

\subsubsection{LCMGPL\index{LCMGPL}}

Subroutine used to recover the {\tt TYPE(C\_PTR)} address of an information block (array of elementary type) from an heterogeneous list,
{\sl without} making a copy of the information. Use of this subroutine must respect the following rules:
\begin{itemize}
\item If the information is modified after the call to {\tt LCMGPL}, a call to {\tt LCMPPL} 
must be performed to acknowledge the modification.
\item The block pointed by {\tt IOFSET} should never be released using a deallocation function such as
{\tt RLSARA}, {\tt deallocate}, etc.
\item The variable {\tt IOFSET} must never be copied into another variable.
\end{itemize}
Non respect of these rules may cause execution failure (core dump,
segmentation fault, etc) without possibility to throw an exception.

\vskip 0.2cm

Subroutine {\tt LCMGPL} implements direct {\sl pinning} on LCM data structures. It represents an advanced capability of the {\sc lcm} API and should only be used in situations where
the economy of computer resources is a critical issue. The {\tt C\_PTR} address is the ANSI~C pointer of a block of
information made available into a Fortran program. If {\tt IOFSET} is a {\tt C\_PTR} address, the useful information is
accessed in a Fortran variable {\tt IDATA} set using
\begin{verbatim}
   USE GANLIB
   ...
   TYPE(C_PTR) :: IOFSET
   INTEGER, POINTER, DIMENSION(:) :: IDATA
   ...
   CALL LCMGPL(IPLIST,ISET,IOFSET)
   CALL C_F_POINTER(IOFSET,IDATA, (/ ILONG /))
\end{verbatim}

The useful information is therefore accessed in memory locations {\tt IDATA(1)} to {\tt IDATA(ILONG)}.

\vskip 0.2cm

A call to {\tt LCMGPL} doesn't cause any modification to the LCM object.

\begin{verbatim}

CALL LCMGPL(IPLIST,ISET,IOFSET)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the block in the list.
A call to {\tt XABORT} is performed if the block does't exist.
The first element of the list is located at index $1$. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IOFSET} &  {\it TYPE(C\_PTR)} & {\tt C\_PTR} address of the information. \\
\hline
\end{tabular}

\subsubsection{LCMPPL\index{LCMPPL}}

Subroutine used to store a block of data (array of elementary type) into an heterogeneous list
{\sl without} making a copy of the information. If the block already exists, it is replaced;
otherwise, it is created. This operation cannot be performed into a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

{\sl If the {\tt ISET}-th component of the heterogeneous list already exists, the address associated
with this component  is replaced by the new address and the information pointed by the old address
is deallocated.}

\vskip 0.2cm

Subroutine {\tt LCMPPL} implements direct {\sl pinning} on LCM data structures. It represents an advanced capability of the {\sc lcm} API and
should only be used in situations where the economy of computer resources is a critical issue. The memory block stored by {\tt LCMPPL} must be previously
allocated by a call to {\tt LCMARA} of the form
\begin{verbatim}
IOFSET=LCMARA(JLONG)
\end{verbatim}

\noindent where {\tt JLONG} is the number of 32-bit words required to store the memory block. {\tt JLONG} is generally equal to {\tt ILONG} except if
{\tt ITYLCM}=4 or {\tt ITYLCM}=6 where {\tt JLONG}={\tt 2*ILONG}.

\vskip 0.2cm

If {\tt ITYLCM}=1, the useful information is accessed in a Fortran variable {\tt IDATA} set using a {\tt C\_F\_POINTER} function:
\begin{verbatim}
   USE GANLIB
   ...
   TYPE(C_PTR) :: IOFSET
   INTEGER, POINTER, DIMENSION(:) :: IDATA
   ...
   IOFSET = LCMARA(ILONG)
   CALL C_F_POINTER(IOFSET,IDATA, (/ ILONG /))
   ...
   CALL LCMPPL(IPLIST,ISET,ILONG,ITYLCM,IOFSET)
\end{verbatim}

The useful information is therefore accessed in memory locations {\tt IDATA(1)} to {\tt IDATA(ILONG)}. There is no need to 
declare {\tt LCMARA} as an external function; this declaration is included in the module set by the {\tt USE GANLIB} statement.
 
\begin{verbatim}

CALL LCMPPL(IPLIST,ISET,ILONG,ITYLCM,IOFSET)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the block in the list.
The first element of the list is located at index $1$. \\
\hline
{\tt ILONG} & {\it INTEGER} & length of the block. \\
\hline
{\tt ITYLCM} & {\it INTEGER} & type of information. =1 32-bit integer; 
                                    =2 32-bit real; =3 {\tt character*4} data; 
				    =4 64-bit real; =5 32-bit logical; =6 64-bit complex;
				    =99 undefined. \\
\hline
{\tt IOFSET} &  {\it TYPE(C\_PTR)} & {\tt C\_PTR} address of the information. Data elements pointed
by {\tt IOFSET} must be initialized before the call to {\tt LCMPPL}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IOFSET} & {\it INTEGER} & {\tt IOFSET=C\_NULL\_PTR} to indicate that the information previously pointed by
                                     {\tt IOFSET} is now managed by {\tt LCM}. \\
\hline
\end{tabular}

\subsection{Management of the associative tables and of the heterogeneous lists}

These functions permit to create ({\tt LCMSIX}, {\tt LCMDID}, {\tt LCMDIL},
{\tt LCMLID}, {\tt LCMLIL}) or to access ({\tt LCMSIX}, {\tt LCMGID}, {\tt LCMGIL})
daughter associative tables or daughter heterogeneous lists. There is no need to 
declare these functions as external functions; this declaration is included in the module set by the {\tt USE GANLIB} statement. Use of these functions is summarized in the following table:

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{daughter} \\
\cline{3-4}
\multicolumn{2}{c|}{} & associative table & heterogeneous list \\
\hline
father & associative table & {\tt LCMDID} & {\tt LCMLID} \\
       &                   & {\tt LCMGID} & {\tt LCMGID} \\
\cline{2-4}
       & heterogeneous list & {\tt LCMDIL} & {\tt LCMLIL} \\
       &                   & {\tt LCMGIL} & {\tt LCMGIL} \\
\hline
\end{tabular}
\end{center}

\subsubsection{LCMDID\index{LCMDID}}

Function used to create or access a daughter associative table included into a father associative table. This operation cannot be
performed in a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

The daughter associative table is created if it doesn't already exist. Otherwise, the
existing daughter associative table is accessed. In the latter case, it is recommended
to use function {\tt LCMGID} which is faster for a simple access and which can be used
with LCM object open in {\tt read-only} mode.

\begin{verbatim}

JPLIST=LCMDID(IPLIST,NAMP)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the father associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the daughter associative table. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt JPLIST} & {\it TYPE(C\_PTR)} & address of the daughter associative table. \\
\hline
\end{tabular}

\subsubsection{LCMLID\index{LCMLID}}

Function used to create or access a daughter heterogeneous list included into a father associative table. This operation cannot be
performed in a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

In the following example, a daughter heterogeneous list is created as a block {\tt LIST}
into a father associative table. The heterogeneous list contains 5~components. A block of data
is stored in each component of the heterogeneous list using {\tt LCMPDL}:

\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IPLIST, JPLIST
      ...
      JPLIST=LCMLID(IPLIST,'LIST',5)
      DO I=1,5
         CALL LCMPDL(JPLIST,I,...
         ...
      ENDDO
\end{verbatim}

\vskip 0.2cm

The heterogeneous list capability is implemented through calls to function {\tt LCMLID}. Such a
call permit the following possibilities:
\begin{itemize}
\item the heterogeneous list is created if it doesn't already exist.
\item the heterogeneous list is accessed if it already exists {\sl and} if its length is unchanged. In this case,
it is recommended to use function {\tt LCMGID} which is faster for a simple access and which can be used
with LCM object open in {\tt read-only} mode.
\item the heterogeneous list is enlarged (components are added) if it already exists {\sl and} if the new length is larger than the preceding one.
\end{itemize}

\begin{verbatim}

JPLIST=LCMLID(IPLIST,NAMP,ILONG)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the father associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the daughter heterogeneous list. \\
\hline
{\tt ILONG} & {\it INTEGER} & number of components in the daughter heterogeneous list. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt JPLIST} & {\it INTEGER} & address of the daughter heterogeneous list named {\tt NAMP}. \\
\hline
\end{tabular}

\subsubsection{LCMLIL\index{LCMLIL}}

Function used to create or access a daughter heterogeneous list included into a father heterogeneous list. This operation cannot be
performed in a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

In the following example, a daughter heterogeneous list is created as {\tt 77}-th component
of a father heterogeneous list. The heterogeneous list contains 5~components. A block of data
is stored in each component of the heterogeneous list using {\tt LCMPDL}:

\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IPLIST, JPLIST
      ...
      JPLIST=LCMLIL(IPLIST,77,5)
      DO I=1,5
         CALL LCMPDL(JPLIST,I,...
         ...
      ENDDO
\end{verbatim}

\vskip 0.2cm

The heterogeneous list capability is implemented through calls to function {\tt LCMLIL}. Such a
call permit the following possibilities:
\begin{itemize}
\item the heterogeneous list is created if it doesn't already exist.
\item the heterogeneous list is accessed if it already exists {\sl and} if its length is unchanged. In this case,
it is recommended to use function {\tt LCMGIL} which is faster for a simple access and which can be used
with LCM object open in {\tt read-only} mode.
\item the heterogeneous list is enlarged (components are added) if it already exists {\sl and} if the new length is larger than the preceding one.
\end{itemize}

\begin{verbatim}

JPLIST=LCMLIL(IPLIST,ISET,ILONG)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the father heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the daughter heterogeneous list in the father heterogeneous list.
The first element of the list is located at index $1$. \\
\hline
{\tt ILONG} & {\it INTEGER} & number of components in the daughter heterogeneous list. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt JPLIST} & {\it TYPE(C\_PTR)} & address of the daughter heterogeneous list. \\
\hline
\end{tabular}

\subsubsection{LCMDIL\index{LCMDIL}}

Function used to create or access a daughter associative table included into a father heterogeneous list. This operation cannot be
performed in a LCM object open in {\tt read-only} mode.

\vskip 0.2cm

The daughter associative table is created if it doesn't already exist. Otherwise, the
existing daughter associative table is accessed. In the latter case, it is recommended
to use function {\tt LCMGIL} which is faster for a simple access and which can be used
with LCM object open in {\tt read-only} mode.

\vskip 0.2cm

It is a good programming practice to replace a set of $N$ distinct associative tables by a
list made of $N$ associative tables, as depicted in \Fig{f1}.

\vskip 0.2cm

\begin{figure}[htbp]
\begin{center} 
\epsfxsize=9cm
\centerline{ \epsffile{vect.eps}}
\parbox{12cm}{\caption{A list of associative tables.}\label{fig:f2}}   
\end{center}  
\end{figure}
\goodbreak

In the example of \Fig{f2}, a set of 5~associative tables, created by {\tt LCMDID}:

\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IPLIST, JPLIST
      CHARACTER HDIR*12
      ...
      DO I=1,5
      WRITE(HDIR,'(5HGROUP,I3,4H/  5)') I
      JPLIST=LCMDID(IPLIST,HDIR)
         CALL LCMPUT(JPLIST,...
         ...
      ENDDO
\end{verbatim}

\noindent are replaced by a list of 5~associative tables, created by {\tt LCMLID} and {\tt LCMDIL}:

\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IPLIST, JPLIST, KPLIST
      ...
      JPLIST=LCMLID(IPLIST,'GROUP',5)
      DO I=1,5
         KPLIST=LCMDIL(JPLIST,I)
         CALL LCMPUT(KPLIST,...
         ...
      ENDDO
\end{verbatim}

\vskip 0.2cm

The capability to include associative tables into an heterogeneous list is implemented using
the {\tt LCMDIL} function:

\begin{verbatim}

JPLIST=LCMDIL(IPLIST,ISET)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the father heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the daughter associative table in the father heterogeneous list.
The first element of the list is located at index $1$. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt JPLIST} & {\it TYPE(C\_PTR)} & address of the daughter associative table. \\
\hline
\end{tabular}

\subsubsection{LCMGID\index{LCMGID}}

Function used to access a daughter associative table {\sl or} heterogeneous list included into a father associative table. 

\begin{verbatim}

JPLIST=LCMGID(IPLIST,NAMP)
\end{verbatim}

\vskip 0.5cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the father associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the daughter associative table or heterogeneous list. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt JPLIST} & {\it TYPE(C\_PTR)} & address of the daughter associative table or heterogeneous list. A call to {\tt XABORT} is performed if this daughter doesn't extst. \\
\hline
\end{tabular}

\subsubsection{LCMGIL\index{LCMGIL}}

Function used to access a daughter associative table {\sl or} heterogeneous list included into a father heterogeneous list. 

\begin{verbatim}

JPLIST=LCMGIL(IPLIST,ISET)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the father heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the daughter associative table or heterogeneous list in the father heterogeneous list.
The first element of the list is located at index $1$. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt JPLIST} & {\it TYPE(C\_PTR)} & address of the daughter associative table or heterogeneous list. A call to {\tt XABORT} is performed if this daughter doesn't extst. \\
\hline
\end{tabular}

\subsubsection{LCMSIX\index{LCMSIX}}

Function used to move across the hierarchical structure of a LCM object made of
associative tables. Using this function, there is no need to remember the names of
the father (grand-father, etc.) associative tables. If a daughter associative table doesn't
exist and if the LCM object is open on creation or modification mode, the daughter
associative table is created. A daughter associative table cannot be created if the
LCM object is open in {\tt read-only} mode.

\vskip 0.4cm

Function {\tt LCMSIX} is deprecated, as {\tt LCMDID} offers a more elegant way to perform the same operation.
However, {\tt LCMSIX} is kept available in the {\sc lcm} API for historical reasons.

\begin{verbatim}

CALL LCMSIX(IPLIST,NAMP,IACT)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table before the call to {\tt LCMSIX}. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} &  name of the daughter associative table if {\tt iact=1}. 
                                   This parameter is not used if {\tt iact=0} or {\tt iact=2}. \\
\hline
{\tt IACT} & {\it INTEGER} & type of move: =0 return towards the root directory of the LCM object; 
                                   =1 move towards the daughter associative table (create it if it doesn't exist); 
				   =2 return towards the father associative table. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table after the call to {\tt LCMSIX}. \\
\hline
\\
\end{tabular}

\vspace{0.4cm}

\subsection{LCM utility functions}

\subsubsection{LCMLIB\index{LCMLIB}}

Function used to print (towards {\tt stdout}) the content of the active directory of an associative table or heterogeneous list.

\begin{verbatim}

CALL LCMLIB(IPLIST)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table or of the heterogeneous list. \\
\hline
\end{tabular}

\subsubsection{LCMEQU\index{LCMEQU}}

Function used to perform a deep-copy of the information contained in an associative table (address {\tt IPLIS1}) 
towards another associative table (address {\tt IPLIS2}). Note that the second associative table (address {\tt IPLIS2}) is modified
but not created by {\tt LCMEQU}.

\begin{verbatim}

CALL LCMEQU(IPLIS1,IPLIS2)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt IPLIS1} & {\it TYPE(C\_PTR)} & address of the existing associative table or of the heterogeneous list
                                    (accessed in {\tt read-only} mode). \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IPLIS2} & {\it TYPE(C\_PTR)} & address of the associative table or of the heterogeneous list, modified by {\tt LCMEQU}. \\
\hline
\end{tabular}

\subsubsection{LCMEXP\index{LCMEXP}}

Function used to export (or import) the content of an associative table towards (or from) a sequential file. The sequential file
can be in binary or {\tt ascii} format.

\vskip 0.4cm

The export of information starts from the active directoty. Note that {LCMEQU} is basically a serialization algorithm
based on the contour algorithm.

\begin{verbatim}

CALL LCMEXP(IPLIST,IMPX,NUNIT,IMODE,IDIR)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table or of the heterogeneous list to be exported (or imported). \\
\hline
{\tt IMPX} & {\it INTEGER} & print parameter (equal to 0 for no print). \\
\hline
{\tt NUNIT} & {\it INTEGER} & unit number of the sequential file. \\
\hline
{\tt IMODE} & {\it INTEGER} & =1 binary sequential file; 
                                    =2 {\sc ascii} sequential file. \\
\hline
{\tt IDIR} & {\it INTEGER} & =1 to export; =2 to import. \\
\hline
\end{tabular}

\subsection{Using fixed-length character arrays}

The following subroutines are implemented using the LCM Fortran API of the preceding sections. They
permit the use of fixed-length character arrays. They reproduce an existing capability of the GANLIB4 API.

\vskip 0.4cm

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{type of operation} \\
\cline{3-4}
\multicolumn{2}{c|}{} & put~~~~~~~~~~~~~ & get~~~~~~~~~~~~~ \\
\hline
father & associative table & {\tt LCMPTC} & {\tt LCMGTC} \\
\cline{2-4}
       & heterogeneous list & {\tt LCMPLC} & {\tt LCMGLC} \\
\hline
\end{tabular}
\end{center}

\subsubsection{LCMGTC\index{LCMGTC}}\label{sect:LCMGTC}

Subroutine used to recover a character array from a block of data stored in an associative table.

\begin{verbatim}

CALL LCMGTC(IPLIST,NAMP,LENG,NLIN,HDATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} &  name of the character array
to recover. A call to {\tt XABORT} is performed if the block does't exist. \\
\hline
{\tt LENG} & {\it INTEGER} & length of each character variable in the array {\tt HDATA}. \\
\hline
{\tt NLIN} & {\it INTEGER} & dimension of array {\tt HDATA}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt HDATA} & {\it CHARACTER*(*)(*)} & character array of dimension $\ge$ {\tt NLIN} in which the character information is to be copied \\
\hline
\end{tabular}

\subsubsection{LCMPTC\index{LCMPTC}}\label{sect:LCMPTC}

Subroutine used to store a character array into a block of data stored in an associative table.
If the block of data already exists, it is updated; otherwise, it is created. This operation cannot be performed
in a LCM object open in {\tt read-only} mode.

\begin{verbatim}

CALL LCMPTC(IPLIST,NAMP,LENG,NLIN,HDATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the character array
to store. \\
\hline
{\tt LENG} & {\it INTEGER} & length of each character variable in the array {\tt HDATA}. \\
\hline
{\tt NLIN} & {\it INTEGER} & dimension of array {\tt HDATA}. \\
\hline
{\tt HDATA} & {\it CHARACTER*(*)(*)} & character array of dimension $\ge$ {\tt NLIN} from which the character information is recovered. \\
\hline
\end{tabular}

\vskip 0.4cm
\goodbreak

\noindent Example:
\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IPLIST
      PARAMETER (ILONG=5)
      CHARACTER*8 HDATA1(ILONG),HDATA2(ILONG)
*
      CALL LCMOP(IPLIST,'mon_dict',0,1,2)
*
* STORE THE INFORMATION.
      HDATA1(1)='string1'
      HDATA1(2)='string2'
      HDATA1(3)='string3'
      HDATA1(4)='string4'
      HDATA1(5)='string5'
      CALL LCMPTC(IPLIST,'node1',8,ILONG,HDATA1)
*
* RECOVER THE INFORMATION.
      CALL LCMGTC(IPLIST,'node1',8,ILONG,HDATA2)
      DO I=1,ILONG
         PRINT *,'I=',I,' RECOVER HDATA2 -->',HDATA2(I),'<--'
      ENDDO
*
      CALL LCMCL(IPLIST,2)
\end{verbatim}

\subsubsection{LCMGLC\index{LCMGLC}}\label{sect:LCMGLC}

Subroutine used to recover a character array from a block of data stored in an heterogeneous list.

\begin{verbatim}

CALL LCMGLC(IPLIST,ISET,LENG,NLIN,HDATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the block in the list.
The first element of the list is located at index $1$. \\
\hline
{\tt LENG} & {\it INTEGER} & length of each character variable in the array {\tt HDATA}. \\
\hline
{\tt NLIN} & {\it INTEGER} & dimension of array {\tt HDATA}. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt HDATA} & {\it CHARACTER*(*)(*)} & character array of dimension $\ge$ {\tt NLIN} in which the character information is to be copied \\
\hline
\end{tabular}

\subsubsection{LCMPLC\index{LCMPLC}}\label{sect:LCMPLC}

Subroutine used to store a character array into a block of data stored in an heterogeneous list.
If the block of data already exists, it is updated; otherwise, it is created. This operation cannot be performed
in a LCM object open in {\tt read-only} mode.

\begin{verbatim}

CALL LCMPLC(IPLIST,USET,LENG,NLIN,HDATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the block in the list.
The first element of the list is located at index $1$. \\
\hline
{\tt LENG} & {\it INTEGER} & length of each character variable in the array {\tt HDATA}. \\
\hline
{\tt NLIN} & {\it INTEGER} & dimension of array {\tt HDATA}. \\
\hline
{\tt HDATA} & {\it CHARACTER*(*)(*)} & character array of dimension $\ge$ {\tt NLIN} from which the character information is recovered. \\
\hline
\end{tabular}

\vskip 0.4cm
\goodbreak

\noindent Example:
\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IPLIST
      PARAMETER (ILONG=5)
      CHARACTER*8 HDATA1(ILONG),HDATA2(ILONG)
*
      CALL LCMOP(IPLIST,'mon_dict',0,1,2)
*
* STORE THE INFORMATION.
      HDATA1(1)='string1'
      HDATA1(2)='string2'
      HDATA1(3)='string3'
      HDATA1(4)='string4'
      HDATA1(5)='string5'
      CALL LCMPLC(IPLIST,1,8,ILONG,HDATA1)
*
* RECOVER THE INFORMATION.
      CALL LCMGLC(IPLIST,1,8,ILONG,HDATA2)
      DO I=1,ILONG
         PRINT *,'I=',I,' RECOVER HDATA2 -->',HDATA2(I),'<--'
      ENDDO
*
      CALL LCMCL(IPLIST,2)
\end{verbatim}

\subsection{Using variable-length character arrays}

The following subroutines are implemented using the LCM Fortran API of the preceding sections. They
permit the use of variable-length character arrays. They represent a {\sl new capability} of the GANLIB5 API.

\vskip 0.4cm

\begin{center}
\begin{tabular}{|c|l|l|l|}
\cline{3-4}
\multicolumn{2}{c|}{} & \multicolumn{2}{c|}{type of operation} \\
\cline{3-4}
\multicolumn{2}{c|}{} & put~~~~~~~~~~~~~ & get~~~~~~~~~~~~~ \\
\hline
father & associative table & {\tt LCMPCD} & {\tt LCMGCD} \\
\cline{2-4}
       & heterogeneous list & {\tt LCMPCL} & {\tt LCMGCL} \\
\hline
\end{tabular}
\end{center}

\subsubsection{LCMGCD\index{LCMGCD}}\label{sect:LCMGCD}

Function used to recover a character array from a block of data stored in an associative table.

\begin{verbatim}

CALL LCMGCD(IPLIST,NAMP,ILONG,HDATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} &  name of the character array
to recover. A call to {\tt XABORT} is performed if the block does't exist. \\
\hline
{\tt ILONG} & {\it INTEGER} & number of components in the character array.\\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt HDATA} & {\it CHARACTER*(*)(*)} & character array of dimension $\ge$ {\tt ILONG} in which the character information is to be copied \\
\hline
\end{tabular}

\subsubsection{LCMPCD\index{LCMPCD}}\label{sect:LCMPCD}

Subroutine used to store a character array into a block of data stored in an associative table.
If the block of data already exists, it is updated; otherwise, it is created. This operation cannot be performed
in a LCM object open in {\tt read-only} mode.

\begin{verbatim}

CALL LCMPCD(IPLIST,NAMP,ILONG,HDATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the associative table. \\
\hline
{\tt NAMP} & {\it CHARACTER*12} & name of the character array
to store. \\
\hline
{\tt ILONG} & {\it INTEGER} & number of components in the character array.\\
\hline
{\tt HDATA} & {\it CHARACTER*(*)(*)} & character array of dimension $\ge$ {\tt ILONG} from which the character information is recovered. \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent Example:
\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IPLIST
      PARAMETER (ILONG=5)
      CHARACTER*16 HDATA1(ILONG),HDATA2(ILONG)
*
      CALL LCMOP(IPLIST,'mon_dict',0,1,2)
*
* STORE THE INFORMATION.
      HDATA1(1)='string1'
      HDATA1(2)='  string2'
      HDATA1(3)='    string3'
      HDATA1(4)='      string4'
      HDATA1(5)='        string5'
      CALL LCMPCD(IPLIST,'node1',ILONG,HDATA1)
*
* RECOVER THE INFORMATION.
      CALL LCMGCD(IPLIST,'node1',ILONG,HDATA2)
      DO I=1,ILONG
         PRINT *,'I=',I,' RECOVER HDATA2 -->',HDATA2(I),'<--'
      ENDDO
*
      CALL LCMCL(IPLIST,2)
\end{verbatim}

\subsubsection{LCMGCL\index{LCMGCL}}\label{sect:LCMGCL}

Subroutine used to recover a character array from a block of data stored in an heterogeneous list.

\begin{verbatim}

CALL LCMGCL(IPLIST,ISET,ILONG,HDATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} &  index of the character array in the heterogeneous list. A call to {\tt XABORT} is performed if the component doesn't exist.
The first element of the list is located at index $1$.\\
\hline
{\tt ILONG} & {\it INTEGER} & number of components in the character array.\\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt HDATA} & {\it CHARACTER*(*)(*)} & character array of dimension $\ge$ {\tt ILONG} in which the character information is to be copied \\
\hline
\end{tabular}

\subsubsection{LCMPCL\index{LCMPCL}}\label{sect:LCMPCL}

Subroutine used to store a character array into a block of data stored in an heterogeneous list.
If the block of data already exists, it is updated; otherwise, it is created. This operation cannot be performed
in a LCM object open in {\tt read-only} mode.

\begin{verbatim}

CALL LCMPCL(IPLIST,ISET,ILONG,HDATA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IPLIST} & {\it TYPE(C\_PTR)} & address of the heterogeneous list. \\
\hline
{\tt ISET} & {\it INTEGER} & index of the character array in the heterogeneous list.
The first element of the list is located at index  $1$. \\
\hline
{\tt ILONG} & {\it INTEGER} & number of components in the character array .\\
\hline
{\tt HDATA} & {\it CHARACTER*(*)(*)} & character array of dimension $\ge$ {\tt ILONG} from which the character information is recovered.  \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent Example:
\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IPLIST, JPLIST
      PARAMETER (ILONG=5)
      CHARACTER*16 HDATA1(ILONG),HDATA2(ILONG)
*
      CALL LCMOP(IPLIST,'mon_dict',0,1,2)
*
* CREATE THE LIST.
      JPLIST=LCMLID(IPLIST,'node2',77)
*
* STORE THE INFORMATION.
      HDATA1(1)='string1'
      HDATA1(2)='  string2'
      HDATA1(3)='    string3'
      HDATA1(4)='      string4'
      HDATA1(5)='        string5'
      CALL LCMPCL(JPLIST,1,ILONG,HDATA1)
*
* RECOVER THE INFORMATION.
      CALL LCMGCL(JPLIST,1,ILONG,HDATA2)
      DO I=1,ILONG
         PRINT *,'I=',I,' RECOVER HDATA2 -->',HDATA2(I),'<--'
      ENDDO
*
      CALL LCMCL(IPLIST,2)
\end{verbatim}

\subsection{Dynamic allocation of an elementary blocks of data in ANSI C}

A function {\tt LCMARA()} and a subroutine {\tt LCMDRD()} are available as wrappers to memory allocator
{\tt setara\_c} and memory deallocator {\tt rlsara\_c} introduced in Sects.~\ref{sect:setara} and~\ref{sect:rlsara}.
{\tt LCLARA()} and {\tt LCMDRD()} offer an alternative to the Fortran-90 {\tt ALLOCATE} and {\tt DEALLOCATE}
capabilities for exceptional situations involving {\sl pinning} towards LCM internal data. Use of {\tt LCLARA()}
and {\tt LCMDRD()} is 64-bit clean and Fortran-2003 compliant, but its use must be avoided as much as possible. A
setara address is a {\tt malloc} pointer, as defined in ANSI-C.

\subsubsection{LCMARA\index{LCMARA}}\label{sect:LCMARA}

{\tt LCMARA()} is a Fortran-2003 wrapper for the ANSI-C function {\tt setara\_c} introduced in Sect.~\ref{sect:setara}. This function
perform a memory allocation and returns a {\tt TYPE(C\_PTR)} pointer variable.

\begin{verbatim}

IDATA_PTR=LCMARA(ILONG)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt ILONG} & {\it INTEGER} & length of the data array (in single-precision words). \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IDATA\_PTR} & {\it TYPE(C\_PTR)} & setara address of the data array. \\
\hline
\end{tabular}

\subsubsection{LCMDRD\index{LCMDRD}}\label{sect:LCMDRD}

{\tt LCMDRD()} is a Fortran-2003 wrapper for the ANSI-C function {\tt rlsara\_c} introduced in Sect.~\ref{sect:rlsara}. This subroutine
deallocate the memory corresponding to a {\tt TYPE(C\_PTR)} pointer variable.

\begin{verbatim}

CALL LCMDRD(IDATA_PTR)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt IDATA\_PTR} & {\it TYPE(C\_PTR)} & setara address of the data array. \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent Example:
\begin{verbatim}
      USE GANLIB
      ...
      TYPE(C_PTR) :: IDATA_PTR
      INTEGER, POINTER, DIMENSION(:) :: IDATA
      ...
      IDATA_PTR=LCMARA(50)
      CALL C_F_POINTER(IDATA_PTR,IDATA,(/ 50 /))
      DO I=1,50
        IDATA(I)=...
      ENDDO
      ...
      CALL LCMDRD(IDATA_PTR)
\end{verbatim}

\subsection{Abnormal termination of the execution}

\subsubsection{XABORT}

Subroutine used to cause the program termination. A message describing the conditions of the
termination is printed.

\vskip 0.2cm

It is important to use this subroutine to abort a program instead of using the {\tt STOP}
statement of Fortran. The {\tt XABORT} subroutine can be used to implement {\sl exception
treatment} in situations where the application software is driven by a multi-physics system.

\vskip 0.2cm

If an abnormal termination occurs, the {\tt XABORT} subroutine is called as
\begin{verbatim}
      CALL XABORT('SUB001: EXECUTION FAILURE.')
\end{verbatim}

\begin{verbatim}

CALL XABORT(HSMG)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt HSMG} & {\it CHARACTER*(*)} & message describing the conditions of the abnormal termination. \\
\hline
\multicolumn{3}{|c|}{\bf value of the function:} \\
\hline
\multicolumn{2}{|l|}{\it void} &  \\
\hline
\end{tabular}

\clearpage

\section {The ISO Fortran {\sc hdf5} API}

The ISO Fortran {\sc hdf5} API is a set of Fortran-2003 wrapper subroutines or functions programmed around the ANSI-C functions of the {\sc hdf5} API presented in Sect.~\ref{sect:hdf5apiC}. This implementation is using
the C interoperability capabilities normalized by ISO and available in the Fortran-2003 compilers. All the subroutines and functions presented in this section are ISO-standard and 64-bit clean.

\vskip 0.08cm

Any subroutines or functions using the Fortran {\sc hdf5} API must include a {\tt USE} statement of the form
\begin{verbatim}
use hdf5_wrap
\end{verbatim}

The address of a HDF5 file is a {\tt TYPE(C\_PTR)} variable declared as
\begin{verbatim}
      type(c_ptr) :: ifile
\end{verbatim}

\subsection{Opening and closing of HDF5 files}

\subsubsection{hdf5\_open\_file\index{hdf5OpenFile}}

Open a HDF5 file.
\begin{verbatim}

call hdf5_open_file(fname, ifile, rdonly)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt fname} & {\it character*1023} & name of the HDF5 file. \\
\hline
{\tt rdonly} & {\it logical} & =.true. to access an existing HDF5 file in {\bf read-only} mode. Optional argument.
By default, the HDF5 file is accessed in read-write mode. \\ 
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
\end{tabular}

\subsubsection{hdf5\_close\_file\index{hdf5CloseFile}}

Close a HDF5 file.

\begin{verbatim}

call hdf5_close_file(ifile)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
\end{tabular}

\vskip 0.8cm

\subsection{Interrogation of HDF5 files}

The data structures in a HDF5 file are self-described. It is therefore possible to
interrogate them in order to know their characteristics.

\subsubsection{hdf5\_list\index{hdf5List}}

List the root table of contents of a group on the standard output. The name of a group can include one or many path separators (character~$\slash$)
to list different hierarchical levels.

\begin{verbatim}

call hdf5_list(ifile, name)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a group. \\
\hline
\end{tabular}

\subsubsection{hdf5\_info\index{hdf5Info}}

Find dataset information.

\begin{verbatim}

call hdf5_info(ifile, name, rank, type, nbyte, dimsr)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt rank} & {\it integer} & rank (number of dimensions) of dataset. \\
\hline
{\tt type} & {\it integer} & type of dataset: =1 32-bit integer; 
                                    =2 32-bit real; =3 character data; 
				    =4 64-bit real. \\
\hline
{\tt nbyte} & {\it integer} & number of bytes in each component of the dataset. \\
\hline
{\tt dimsr} & {\it integer(*)} & integer array containing the dimension of dataset. {\tt rank} values are provided. \\
\hline
\end{tabular}

\subsubsection{hdf5\_get\_dimensions\index{hdf5GetDimensions}}

Find the rank (number of dimensions) of a dataset.

\begin{verbatim}

rank=hdf5_get_dimensions(ifile, name)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt rank} & {\it integer} & rank of the dataset. \\
\hline
\end{tabular}

\subsubsection{hdf5\_get\_shape\index{hdf5GetShape}}

Find the shape (dimension array) of a dataset.

\begin{verbatim}

call hdf5_get_shape(ifile, name, dimsr)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt dimsr} & {\it integer(*)} & integer array containing the dimension of dataset. {\tt rank} values are provided. \\
\hline
\end{tabular}

\subsubsection{hdf5\_list\_datasets\index{hdf5ListDatasets}}

Allocate a character array of the correct size and recover character daughter dataset names in a group.

\begin{verbatim}

call hdf5_list_datasets(ifile, name, dsets)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{4.5cm}|p{8.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt idata} & {\it character*1023(:),allocatable} & list of character names of each daughter dataset.\\
\hline
\end{tabular}

\vskip 0.5cm

\noindent Example:
\begin{verbatim}
  use hdf5_wrap
  type(c_ptr) :: ifile
  character(len=100), allocatable :: list(:)
  ...
  call hdf5_list_datasets(ifile, '/', list)
  write(*,*) 'dataset table of contents:'
  do i = 1, size(list)
    write(*,*) trim(list(i))
  enddo
  deallocate(list)
\end{verbatim}

\subsubsection{hdf5\_list\_groups\index{hdf5ListGroups}}

Allocate a character array of the correct size and recover character daughter group names in a group.

\begin{verbatim}

call hdf5_list_groups(ifile, name, dsets)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{4.5cm}|p{8.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt idata} & {\it character*1023(:),allocatable} & list of character names of each daughter group.\\
\hline
\end{tabular}

\vskip 0.5cm

\noindent Example:
\begin{verbatim}
  use hdf5_wrap
  type(c_ptr) :: ifile
  character(len=100), allocatable :: list(:)
  ...
  call hdf5_list_groups(ifile, '/', list)
  write(*,*) 'group table of contents:'
  do i = 1, size(list)
    write(*,*) trim(list(i))
  enddo
  deallocate(list)
\end{verbatim}

\subsubsection{hdf5\_group\_exists\index{hdf5GroupExists}}

Test for existence of a group.

\begin{verbatim}

ierr=hdf5_group_exists(ifile, name)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a group. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt ierr} & {\it logical} & existence flag: =.true. if the group exists. \\
\hline
\end{tabular}

\vskip 0.8cm

\subsection{Management of groups and datatypes}

\subsubsection{hdf5\_create\_group\index{hdf5CreateGroup}}

Create a group.

\begin{verbatim}

call hdf5_create_group(ifile, name)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of the group to create. \\
\hline
\end{tabular}

\vskip 0.8cm

\subsubsection{hdf5\_read\_data\index{hdf5ReadData}}

Allocate an array of the correct type and size and copy a dataset from HDF5 file into memory.

\begin{verbatim}

call hdf5_read_data(ifile, name, data)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a dataset. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3.5cm}|p{9.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt data} & {\it class(:),allocatable} & array. Note: if the array is replaced by a single integer, real or characcter variable,
this variable has not the allocatable status.\\
\hline
\end{tabular}

\vskip 0.5cm

\noindent The generic {\it class(:),allocatable} data type is selected among the following options:

\vskip 0.2cm
\begin{tabular}{|p{10.5cm}|}
\hline
{\tt integer  :: data} \\
{\tt integer, allocatable, dimension(:) :: data} \\
{\tt integer, allocatable, dimension(:,:) :: data} \\
{\tt real(4) :: data} \\
{\tt real(4), allocatable, dimension(:) :: data} \\
{\tt real(4), allocatable, dimension(:,:) :: data} \\
{\tt real(4), allocatable, dimension(:,:,:) :: data} \\
{\tt real(4), allocatable, dimension(:,:,:,:) :: data} \\
{\tt real(8) :: data} \\
{\tt real(8), allocatable, dimension(:) :: data} \\
{\tt real(8), allocatable, dimension(:,:) :: data} \\
{\tt real(8), allocatable, dimension(:,:,:) :: data} \\
{\tt real(8), allocatable, dimension(:,:,:,:) :: data} \\
{\tt character(len=*) :: data} \\
{\tt character(len=*), allocatable, dimension(:) :: data} \\
\hline
\end{tabular}

\vskip 0.4cm
\goodbreak

\noindent Example 1:
\begin{verbatim}
  use hdf5_wrap
  type(c_ptr) :: ifile
  integer :: ncalc
  ...
  call hdf5_read_data(ifile,"NCALS",ncalc)
  write(*,*) 'ncalc=',ncalc
\end{verbatim}

\vskip 0.3cm

\noindent Example 2:
\begin{verbatim}
  use hdf5_wrap
  type(c_ptr) :: ifile
  character(len=8), allocatable, dimension(:) :: isoname
  ...
  call hdf5_read_data(ifile,"/explicit/ISONAME",isoname)
  write(*,*) 'isotope names:'
  do i = 1, size(isoname)
    write(*,*) trim(isoname(i))
  enddo
  deallocate(isoname)
\end{verbatim}

\vskip 0.3cm

\noindent Example 3:
\begin{verbatim}
  use hdf5_wrap
  type(c_ptr) :: ifile
  real(8), allocatable, dimension(:,:) :: yields_matrix
  ...
  call hdf5_read_data(ifile,"/physconst/FYIELDS",yields_matrix)
  no_fiss=size(yields_matrix,1)
  no_fp=size(yields_matrix,2)
  write(*,*) 'no_fiss=',no_fiss,' no_fp=',no_fp
  deallocate(yields_matrix)
\end{verbatim}

\subsubsection{hdf5\_write\_data\index{hdf5WriteData}}

Copy an array from memory into a HDF5 dataset

\begin{verbatim}

call hdf5_write_data(ifile, name, idata)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ifile} & {\it type(c\_ptr)} & address of the HDF5 file. \\
\hline
{\tt name} & {\it character*1023} & name of a dataset. \\
\hline
{\tt data} & {\it class(*)} & array.\\
\hline
\end{tabular}

\vskip 0.5cm
\goodbreak

\noindent The generic {\it class(*)} data type is selected among the following options:

\vskip 0.2cm
\begin{tabular}{|p{8.5cm}|}
\hline
{\tt integer,intent(in) :: data} \\
{\tt integer,dimension(:) :: data} \\
{\tt integer,dimension(:,:) :: data} \\
{\tt real(4) :: data} \\
{\tt real(4),dimension(:) :: data} \\
{\tt real(4),dimension(:,:) :: data} \\
{\tt real(4),dimension(:,:,:) :: data} \\
{\tt real(4),dimension(:,:,:,:) :: data} \\
{\tt real(8) :: data} \\
{\tt real(8),dimension(:) :: data} \\
{\tt real(8),dimension(:,:) :: data} \\
{\tt real(8),dimension(:,:,:) :: data} \\
{\tt real(8),dimension(:,:,:,:) :: data} \\
{\tt character(len=*) :: data} \\
{\tt character(len=*), dimension(:) :: data} \\
\hline
\end{tabular}

\vskip 0.4cm

\noindent Example:
\begin{verbatim}
  use hdf5_wrap
  type(c_ptr) :: ifile
  integer, allocatable, dimension(:) :: nitmaV1
  ...
  allocate(nitmaV1(10))
  nitmaV1(:10)=100
  call hdf5_write_data(ifile, 'my_dummy_record', nitmaV1)
  deallocate(nitmaV1)
\end{verbatim}

\clearpage

\section {The ISO Fortran CLE-2000 API}

\subsection {Management of Fortran files outside CLE-2000}

The {\tt KDROPN} utility is a general system for managing Fortran files in a software application.

\subsubsection{KDROPN\index{KDROPN}}

Function used to open a file and allocate its unit number. Allocate a unit number to file
name. If unit is already opened, returns its address. Sequential (formatted
or not) and direct access (DA) files are permitted.

\begin{verbatim}

IFILE=KDROPN(CUNAME,IACTIO,IUTYPE,LRDA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt CUNAME} & {\it CHARACTER*(*)}  &  file name. If {\tt cuname}$=${\tt ' '}, use a default name. \\
\hline
{\tt IACTIO} & {\it INTEGER}  & action on file.
$=0$: to allocate a new file;
$=1$: to access and modify an existing file;
$=2$: to access an existing file in {\tt read-only} mode.  \\
\hline
{\tt IUTYPE} & {\it INTEGER}  & file type. 
$=1$:  (not used);
$=2$:  sequential unformatted;
$=3$:  sequential formatted;
$=4$:  direct access (DA) unformatted file.  \\
\hline
{\tt LRDA} & {\it INTEGER}  & number of words in a DA record (used if {\tt IUTYPE} $= 4$).  \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IFILE} & {\it INTEGER}  & unit number of the allocated file. Equal to the error code if the allocation failed.  \\
\hline
\end{tabular}

\subsubsection{KDRCLS\index{KDRCLS}}

Function used to close a file and release its unit number.

\begin{verbatim}

IER=KDRCLS(IFILE,IACTIO)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IFILE} & {\it INTEGER} &  unit number of the allocated file (as returned by {\tt KDROPN}). \\
\hline
{\tt IACTIO} & {\it INTEGER}  & action on file.
$=1$: to keep the file;
$=2$: to delete the file.  \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IER} & {\it INTEGER}  & error code. Equal to zero if the close is successful.  \\
\hline
\end{tabular}

\clearpage

\subsection {Management of word-addressable (KDI) files outside CLE-2000}

The {\tt KDIOP} utility is a general system for managing word-addressable (KDI) files in a software application.

\subsubsection{KDIOP\index{KDIOP}}

Function used to open a KDI file and allocate its header.

\begin{verbatim}

MY_FILE=KDIOP(CUNAME,IACTIO)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt CUNAME} & {\it CHARACTER*(*)}  &  file name.  \\
\hline
{\tt IACTIO} & {\it INTEGER}  & action on file.
$=0$: to allocate a new file;
$=1$: to access and modify an existing file;
$=2$: to access an existing file in {\tt read-only} mode.  \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt MY\_FILE} & {\it TYPE(C\_PTR)}  & address of the allocated file. Equal to {\tt C\_NULL\_PTR} if the allocation failed.  \\
\hline
\end{tabular}

\subsubsection{KDIGET\index{KDIGET}}

Subroutine used to read a data array from a KDI file at offset {\tt IOFSET}.

\begin{verbatim}

CALL KDIGET(MY_FILE, IDATA, IOFSET, LENGTH)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt MY\_FILE} & {\it TYPE(C\_PTR)} &  address of the allocated file (as returned by {\tt KDIOP}). \\
\hline
{\tt IOFSET} & {\it INTEGER}  & offset of the information in the KDI file. \\
\hline
{\tt LENGTH} & {\it INTEGER}  & length of the array of information, in unit of 32-bit words. \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IDATA} & {\it INTEGER}  & array of information.  \\
\hline
\end{tabular}

\subsubsection{KDIPUT\index{KDIPUT}}

Subroutine used to store a data array in a KDI file at offset {\tt IOFSET}.

\begin{verbatim}

CALL KDIPUT(MY_FILE, IDATA, IOFSET, LENGTH)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt MY\_FILE} & {\it TYPE(C\_PTR)} &  address of the allocated file (as returned by {\tt KDIOP}). \\
\hline
{\tt IDATA} & {\it INTEGER}  & array of information.  \\
\hline
{\tt IOFSET} & {\it INTEGER}  & offset of the information in the KDI file. \\
\hline
{\tt LENGTH} & {\it INTEGER}  & length of the array of information, in unit of 32-bit words. \\
\hline
\end{tabular}

\subsubsection{KDICL\index{KDICL}}

Function used to close a KDI file.

\begin{verbatim}

IER=KDICL(MY_FILE,IACTIO)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt MY\_FILE} & {\it TYPE(C\_PTR)} &  address of the allocated file (as returned by {\tt KDIOP}). \\
\hline
{\tt IACTIO} & {\it INTEGER}  & action on file.
$=1$: to keep the file;
$=2$: to delete the file.  \\
\hline
\end{tabular}

\vskip 0.4cm
\goodbreak
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IER} & {\it INTEGER}  & error code. Equal to zero if the close is successful.  \\
\hline
\end{tabular}

\subsection {Management of Fortran and KDI files used as CLE-2000 parameters}

CLE-2000 allows a module of the application software to exchange information using LCM objects and files. If the
application software is programmed in Fortran, the CLE-2000 driver expects all these parameters to be {\tt TYPE(C\_PTR)}
variables. The ISO Fortran CLE-2000 API defines a collection of four functions to wrap the {\tt KDROPN} utility
in such a way that Fortran files are  referred by {\tt TYPE(C\_PTR)} variables.

\subsubsection{FILOPN\index{FILOPN}}

Function used to open a file and allocate its unit number. Allocate a unit number to file
name. If unit is already opened, returns its address. Word addressable (KDI), sequential (formatted
or not) and direct access (DA) files are permitted.
This function is a GANLIB wrapper for the {\tt KDROPN} and {\tt KDIOP} utilities.

\begin{verbatim}

IFILE=FILOPN(CUNAME,IACTIO,IUTYPE,LRDA)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt CUNAME} & {\it CHARACTER*(*)}  &  file name. If {\tt cuname}$=${\tt ' '}, use a default name. \\
\hline
{\tt IACTIO} & {\it INTEGER}  & action on file.
$=0$: to allocate a new file;
$=1$: to access and modify an existing file;
$=2$: to access an existing file in {\tt read-only} mode.  \\
\hline
{\tt IUTYPE} & {\it INTEGER}  & file type. 
$=1$:  KDI word addressable file;
$=2$:  sequential unformatted;
$=3$:  sequential formatted;
$=4$:  direct access (DA) unformatted file.  \\
\hline
{\tt LRDA} & {\it INTEGER}  & number of words in a DA record (used if {\tt IUTYPE} $= 4$).  \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IFILE} & {\it TYPE(FIL\_file)}  & handle to the allocated file. Equal to {\tt C\_NULL\_PTR} if the allocation failed.  \\
\hline
\end{tabular}

\subsubsection{FILCLS\index{FILCLS}}

Function used to close a file and release its unit number.
This function is a GANLIB wrapper for the {\tt KDRCLS} and {\tt KDICL} utilities.

\begin{verbatim}

IER=FILCLS(MY_FILE,IACTIO)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt MY\_FILE} & {\it TYPE(FIL\_file)} &  handle to the allocated file (as returned by {\tt FILOPN}). \\
\hline
{\tt IACTIO} & {\it INTEGER}  & action on file.
$=1$: to keep the file;
$=2$: to delete the file.  \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IER} & {\it INTEGER}  & error code. Equal to zero if the close is successful.  \\
\hline
\end{tabular}

\subsubsection{FILUNIT\index{FILUNIT}}

Function used to recover the Fortran file unit number

\begin{verbatim}

IUNIT=FILUNIT(FILE_PT)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt FILE\_PT} & {\it TYPE(C\_PTR)} &  address of the allocated file ({\tt c\_loc(MY\_FILE)}, as returned by {\tt FILOPN}). \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IUNIT} & {\it INTEGER}  & file unit number. Equal to $-1$ in case of error. \\
\hline
\end{tabular}

\subsubsection{FILKDI\index{FILKDI}}

Function used to recover the address of the KDI file.

\begin{verbatim}

KDI_PT=FILKDI(FILE_PT)
\end{verbatim}

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameter:} \\
\hline
{\tt FILE\_PT} & {\it TYPE(C\_PTR)} &  address of the allocated file ({\tt c\_loc(MY\_FILE)}, as returned by {\tt FILOPN}). \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt KDI\_PT} & {\it TYPE(C\_PTR)}  & address of the KDI file. Equal to {\tt C\_NULL\_PTR} if case of error.  \\
\hline
\end{tabular}

\subsection {The main entry point for CLE-2000}

Function {\tt KERNEL} is a Fortran wrapper around function {\tt cle2000\_c()} to serve as the main entry point for CLE-2000.
Function {\tt KERNEL} is specialized to the case where the application software is executed in stand-alone mode. It is
therefore limited to the simple case where a CLE-2000 procedure has no parameters and no in-out CLE-2000 variables.
Moreover, the main CLE-2000 procedure is recovered from the standard unit (i.e., from unit 5) and is assumed to have a {\tt .x2m}
suffix. This limitation is making sense as no multi-physics system is currently programmed in Fortran.

\subsubsection{KERNEL\index{KERNEL}}

The general specification of function {\tt KERNEL} is

\begin{verbatim}

IER=KERNEL(DUMMOD,IPRINT)
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt DUMMOD} & {\it EXTERNAL} & external C-interoperable Fortran-2003 function responsible for dispatching the execution among calculation modules.   \\
\hline
{\tt IPRINT} & {\it INTEGER} & print parameter (set to zero for no print). \\
\hline
\end{tabular}

\vskip 0.4cm
\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameter:} \\
\hline
{\tt IER} & {\it INTEGER}  &  error code. Equal to zero if the execution of {\tt KERNEL} is successful.   \\
\hline
\end{tabular}

\subsubsection{DUMMOD\index{DUMMOD}}

Function {\tt KERNEL} has one of its arguments that is a developer-defined external function. Function {\tt DUMMOD} is a C-interoperable Fortran-2003 function responsible for dispatching the execution among calculation modules. An instance of function {\tt DUMMOD} is implemented for 
each Fortran application software using the GANLIB.

\vskip 0.08cm

A stand-alone GANLIB application can be set by using the following implementation of {\tt GANMOD}
\begin{verbatim}
!
!-----------------------------------------------------------------------
!
!Purpose:
! Dispatch to a calculation module in GANLIB. ANSI-C interoperable.
!
!Copyright:
! Copyright (C) 2009 Ecole Polytechnique de Montreal
! 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.
!
!Author(s): A. Hebert
!
!-----------------------------------------------------------------------
!
integer(c_int) function GANMOD(cmodul, nentry, hentry, ientry, jentry, &
               kentry, hparam_c) bind(c)
!
   use GANLIB
   implicit none
!----
!  subroutine arguments
!----
   character(kind=c_char), dimension(*) :: cmodul
   integer(c_int), value :: nentry 
   character(kind=c_char), dimension(13,*) :: hentry
   integer(c_int), dimension(nentry) :: ientry, jentry
   type(c_ptr), dimension(nentry) :: kentry
   character(kind=c_char), dimension(73,*) :: hparam_c
!----
!  local variables
!----
   integer :: i, ier
   character :: hmodul*12, hsmg*131, hparam*72
   character(len=12), allocatable :: hentry_f(:)
   type(c_ptr) :: my_file
   integer, external :: GANDRV
!
   allocate(hentry_f(nentry))
   call STRFIL(hmodul, cmodul)
   do i=1,nentry
      call STRFIL(hentry_f(i), hentry(1,i))
      if(ientry(i) >= 3) then
!        open a Fortran file.
         call STRFIL(hparam, hparam_c(1,i))
         my_file=FILOPN(hparam,jentry(i),ientry(i)-1,0)
         if(.not.c_associated(my_file)) then
            write(hsmg,'(29hGANMOD: unable to open file '',a12,2h''.)') hentry_f(i)
            call XABORT(hsmg)
         endif
         kentry(i)=my_file
      endif
   enddo
!  ----------------------------------------------------------
   GANMOD=GANDRV(hmodul,nentry,hentry_f,ientry,jentry,kentry)
!  ----------------------------------------------------------
   do i=1,nentry
      if(ientry(i) >= 3) then
!        close a Fortran file.
         ier=FILCLS(kentry(i),1)
         if(ier < 0) then
            write(hsmg,'(30hGANMOD: unable to close file '',a12,2h''.)') hentry_f(i)
            call XABORT(hsmg)
         endif
      endif
   enddo
   deallocate(hentry_f)
   flush(6)
   return
end function GANMOD
\end{verbatim}

\noindent with function {\tt GANDRV} implemented as
\begin{verbatim}
integer function GANDRV(hmodul,nentry,hentry,ientry,jentry,kentry)
!
!-----------------------------------------------------------------------
!
!Purpose:
! standard utility operator driver for Ganlib.
!
!Copyright:
! Copyright (C) 2002 Ecole Polytechnique de Montreal
! 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
!
!Author(s): A. Hebert
!
!Parameters: input/output
! hmodul  name of the operator.
! nentry  number of LCM objects or files used by the operator.
! hentry  name of each LCM object or file.
! ientry  type of each LCM object or file:
!         =1 LCM memory object; =2 XSM file; =3 sequential binary file;
!         =4 sequential ascii file.
! jentry  access of each LCM object or file:
!         =0 the LCM object or file is created;
!         =1 the LCM object or file is open for modifications;
!         =2 the LCM object or file is open in read-only mode.
! kentry  LCM object address or file unit number.
!
!Parameters: output
! kdrstd  completion flag (=0: operator hmodul exists; =1: does not exists).
!
!-----------------------------------------------------------------------
!
!----
!  subroutine arguments
!----
   use GANLIB
   integer nentry
   character hmodul*(*),hentry(nentry)*12
   integer ientry(nentry),jentry(nentry)
   type(c_ptr) kentry(nentry)
!
   GANDRV=0
   if(hmodul == 'EQU:' )then
!     standard equality module.
      call DRVEQU(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'GREP:') then
!     standard grep module.
      call DRVGRP(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'UTL:') then
!     standard LCM/XSM utility module.
      call DRVUTL(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'ADD:') then
!     standard addition module.
      call DRVADD(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'MPX:') then
!     standard multiplication module.
      call DRVMPX(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'STAT:') then
!     standard compare module.
      call DRVSTA(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'BACKUP:') then
!     standard backup module.
      call DRVBAC(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'RECOVER:') then
!     standard recovery module.
      call DRVREC(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'FIND0:') then
!     standard module to find zero of a continuous function.
      call DRV000(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'MSTR:') then
!     manage user-defined structures.
      call MSTR(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'MODUL1:') then
!     user-defined module.
      call DRVMO1(nentry,hentry,ientry,jentry,kentry)
   else if(hmodul == 'ABORT:') then
!     requested abort.
      call XABORT('GANDRV: requested abort.')
   else
      GANDRV=1
   endif
   return
end function GANDRV
\end{verbatim}

\subsection {The free-format input reader}

Subroutines {\tt REDOPN}, {\tt REDGET}, {\tt REDPUT} and {\tt REDCLS} are Fortran wrappers around ANSI~C functions {\tt redopn\_c()}, {\tt redget\_c()}, {\tt redput\_c()} and {\tt redcls\_c()}.
Only {\tt REDGET} and {\tt REDPUT} are expected to be used in an application software.

\subsubsection{REDOPN\index{REDOPN}}

Subroutine {\tt REDOPN} is called to open the input reader. The general specification of function {\tt REDOPN} is

\begin{verbatim}

CALL REDOPN(IINP1,IOUT1,NREC)
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2.5cm}|p{10.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt IINP1} & {\it TYPE(C\_PTR)} & KDI object containing the CLE-2000 input data.\\
\hline
{\tt IOUT1} & {\it INTEGER} & unit number of the sequential {\sc ascii} file used to write execution messages. Can be set to 6 for standard output. \\
\hline
{\tt NREC} & {\it INTEGER} & record index where reading occurs. Can be set to zero at first call. Set to the value returned by {\tt REDCLS} at subsequent calls.\\
\hline
\end{tabular}

\subsubsection{REDGET\index{REDGET}}

Subroutine {\tt REDGET} is called within modules of the application software to recover the module-specific input data.
The general specification of function {\tt REDGET} is

\begin{verbatim}

CALL REDGET(ITYP,NITMA,FLOTT,TEXT,DFLOT)
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt ITYP} & {\it INTEGER} & type of the CLE-2000 variable. A negative value indicates that the variable is to be computed by the application software and returned towards CLE-2000 using a call to {\tt redput\_c}. $=\pm 1$: integer type;
$=\pm 2$: real (single precision) type;
$=\pm 3$: string type;
$=\pm 4$: double precision type;
$=\pm 5$: logical type.\\
\hline
{\tt NITMA} & {\it INTEGER} & integer input value when {\tt ITYP} $= 1$ or $= 5$;  number of characters when {\tt ITYP} $= 3$. \\
\hline
{\tt FLOTT} & {\it REAL} &  real input value when {\tt ITYP} $= 2$.  \\
\hline
{\tt TEXT} & {\it CHARACTER*(*)} & character string input value when {\tt ITYP} $= 3$.   \\
\hline
{\tt DFLOT} & {\it DOUBLE PRECISION} & double precision input value when {\tt ITYP} $= 4$.   \\
\hline
\end{tabular}

\subsubsection{REDPUT\index{REDPUT}}

Subroutine {\tt REDPUT} is called within modules of the application software to make information computed by the module available as CLE-2000 variables to the CLE-2000 procedure.
The application software must first call {\tt REDGET} and obtain a negative value of {\tt ITYP}. A call to {\tt REDPUT} is next performed with its first parameter set to
$-${\tt ITYP} (now, a positive value) and with the corresponding value of the parameter.
The general specification of function {\tt REDPUT} is

\begin{verbatim}

CALL REDPUT(ITYP,NITMA,FLOTT,TEXT,DFLOT)
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|}
\hline
\multicolumn{3}{|c|}{\bf input parameters:} \\
\hline
{\tt ITYP} & {\it INTEGER} & type of the CLE-2000 variable. $=1$: integer type;
$=2$: real (single precision) type;
$=3$: string type;
$=4$: double precision type;
$=5$: logical type.\\
\hline
{\tt NITMA} & {\it INTEGER} & integer output value when {\tt ITYP} $= 1$ or $= 5$;  number of characters when {\tt ITYP} $= 3$. \\
\hline
{\tt FLOTT} & {\it REAL} &  real output value when {\tt ITYP} $= 2$. \\
\hline
{\tt TEXT} & {\it CHARACTER*(*)} & character string output value when {\tt ITYP} $= 3$.  \\
\hline
{\tt DFLOT} & {\it DOUBLE PRECISION} & double precision output value when {\tt ITYP} $= 4$.  \\
\hline
\end{tabular}

\subsubsection{REDCLS\index{REDCLS}}

Subroutine {\tt REDCLS} is called to close the input reader.
The general specification of function {\tt REDCLS} is

\begin{verbatim}

CALL REDCLS(IINP1,IOUT1,NREC)
\end{verbatim}

\vskip 0.8cm

\noindent
\begin{tabular}{|p{1.5cm}|p{2.5cm}|p{10.5cm}|}
\hline
\multicolumn{3}{|c|}{\bf output parameters:} \\
\hline
{\tt IINP1} & {\it TYPE(C\_PTR)} & KDI object containing the CLE-2000 input data.\\
\hline
{\tt IOUT1} & {\it INTEGER} & unit number of the sequential {\sc ascii} file used to write execution messages. \\
\hline
{\tt NREC} & {\it INTEGER} & record index where reading occurs. \\
\hline
\end{tabular}

\section{The Python3 {\sc lcm} API}

The Python3 {\sc lcm} API, or Py{\sc lcm} API, is a component of the PyGan library, available in the Version5 distribution.
PyGan is a Python3 library made of three classes, as depicted in Fig.~\ref{fig:PyGan}, so as to encapsulate Ganlib5 capabilities.
The extension module {\tt lcm} contains a class providing {\sl in-out} support of {\sl hererogeneous lists} and
{\sl associative tables}, as implemented in the {\sc lcm} API of Sect.~\ref{sect:lcmapiC}, to Python3 users.

\begin{figure}[htbp]
\begin{center} 
\epsfxsize=2.4cm
\centerline{ \epsffile{cle2000_hierarchy_uml.eps}}
\parbox{12cm}{\caption{The PyGan class model.}\label{fig:PyGan}}
\end{center}  
\end{figure}

\vskip 0.2cm

{\sl Associative tables} in Ganlib5 are similar to Python dictionaries and can be handled
as such in the Python3 dataset.  Each element of an associative table
 is associated with a string.
{\sl Hererogeneous lists} in Ganlib5 are similar to Python lists and therefore are an ordered set
of elements. Each list element is identified by an index and contains
an information block. As for the information blocks, they are either
strings, or NumPy arrays.\opcite {npython}
A PyLCM object can physically be, either in memory or located on a {\sc xsm} file.

\vskip 0.2cm

{\sl LCM Python bindings} allow Python to use the API
{\sc lcm} transparently. Associative tables and heterogeneous lists are
represented as Python dictionaries and Python lists, respectively. The
information blocks in integer and floating point {\sc lcm} or {\sc xsm} arrays
are automatically transformed into {\sl numpy} arrays.
Methods of the {\sc lcm} API have been adapted to manage the use of files.

\vskip 0.2cm

The compilation and link edition of the API require the definition of a UNIX environment variable {\tt FORTRANPATH} pointing towards the {\tt libgfortran.a} library
compatible with your operating system. On a OSX operating system, this variable may be set as
\begin{verbatim}
export FORTRANPATH=/usr/local/lib/gcc/11/ # contains libgfortran.a
\end{verbatim}
\noindent On a Linux operating system, the environment variable is set as
\begin{verbatim}
export FORTRANPATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/ # contains libgfortran.so
\end{verbatim}

\subsection{Structures}

\begin{description}
\item[Associative tables] An associative table is equivalent to a Python dictionary.
Each element of a table is an association between a string of 12
characters and an information block (scalar value or vector
of a given type). Associative tables can contain lists or other tables
associative and thus form a tree structure.

\item[Heterogeneous lists] A list is an ordered set of elements of heterogeneous types. Each element is
accessed by an integer index and contains an information block.
Lists can contain scalar values or elementary information blocks,
as written in the next section. Lists can also contain
child lists or other associative tables.

\item[Elementary information blocks] An elementary information block constitutes a set of values whose Dragon5/Donjon5 module
needs to perform the calculation. Unlike tables or lists
which only allow you to order information, the elementary information block is the useful data
to be used in a calculation. A block of information is either strings of characters,
either numerical arrays (array) with one dimension (similar to {\sl numpy} arrays).
The elementary blocks of information belong to one of the following types:

\begin{tabular} {| p {3.0cm} | p {11.5cm} |}
\hline
Int array & An item of the associative table can correspond to an array of
32-bit integers (type~{\tt l} from NumPy).\\
Float32 array & An item of the associative table can correspond to an array of
32-bit reals (type~{\tt f} from NumPy).\\
Character array & An item of the associative table can correspond to an array of
of characters (array of type {\tt Char} from Python).\\
Float64 array & An item of the associative table can correspond to an array of
64-bit reals (type~{\tt d} from NumPy) \\
Logical32 array & An item of the associative table can correspond to an array of
32-bit integers (type~{\tt i} from NumPy containing 1/0 to denote true/false).\\
Complex32 array & An associative table item can correspond to an array of of 64-bit complex variables (type~{\tt F} from NumPy).\\
\hline
\end{tabular}

\end{description}

\subsection{LCM object Python API} \label {sect: APIP}

The {\tt lcm} module, accessible from Python3, is imported by the command
\begin{verbatim}
import lcm
\end{verbatim}
It has one constructor: {\tt lcm.new()}, used to create an {\sl object instance} {\tt o}.

\subsubsection{Attribute Variables \index {attribute variables}}

A PyLCM object {\tt o} contains six attribute variables. The first five are read-only; {\tt o.\_impx} has read-write access.

\begin {description}
\item [{\tt o.\_name}] Python (len=72) name of the PyLCM object containing the root
\item [{\tt o.\_directory}] Name (len=12) of the current directory. $=$ {\tt '/'} for the
root directory. This attribute variable is undefined for
lists and for files created by {\tt lcm.file()}.
\item [{\tt o.\_long}] $ = - 1 $: associative table; $ \ge 1 $: heterogeneous list of length {\tt o.\_long}.
\item [{\tt o.\_type}] Type of the object. $ = 1 $: LCM object in memory
(similar to a Python dictionary); $ = 2 $: persistent LCM object (of type {\sc xsm} file);
$ = 3 $: binary sequential file; $ = 4 $: sequential {\sc ascii} file; $=$ 5:
direct access file; $=$ 6: HDF5 file.
\item [{\tt o.\_access}] Access mode of the object. $ = 0 $: closed object (i.e., not
accessible); $ = 1 $: object in modification mode; $ = 2 $: object in read mode
(read-only).
\item [{\tt o.\_impx}] Edition index for the object ($=0$ for minimum printouts).
\end {description}

\subsubsection{lcm.new()}

This method is used to create a PyLCM object made up of an associative table or of a file. A {\sc lcm} object is a {\sl memory-resident} structure
implemented with the {\sc lcm} API of Sect.~\ref{sect:lcmapiC}. A {\sc xsm} object store similar information in a direct access file and is implemented with the same API. This object occupies very little memory space and can be
used to store very large objects whose maximum dimension is not
limited only by the available disk space. In general, we can always replace
a ``memory'' PyLCM object  by a persistent PyLCM object (at the cost of a certain
increase in CPU time). A persistent PyLCM object can
also be used as archiving medium for a ``memory'' PyLCM object.

\vskip 0.2cm

This {\tt new} constructor is used to perform the following actions:
\begin{itemize}
\item for creating a new empty PyLCM object;
\item for retrieving a file made by a Dragon5/Donjon5 module or to transfer a file to a Dragon5/Donjon5 module. At the end of this call, the variable
attribute {\tt o.\_access} is equal to $1$ or  $2$. The PyLCM object thus created does not have
the {\tt \_directory} and {\tt \_long} attributes. It does not own the {\tt keys()},
{\tt lib()}, {\tt rep()}, {\tt lis()} and {\tt copy()} methods;
\item to create a PyLCM object containing a memory or persistent LCM object from the serialized information contained in a sequential file (import action);
\item to serialize the content of an existing PyLCM object containing a memory or persistent LCM object into a sequential file (export action);
\item to perform a deep copy of an existing PyLCM object containing a memory or persistent LCM object into another.
\end{itemize}

\begin{verbatim}
o = lcm.new(type, [name], [iact], [pyobj], [lrda], [impx])
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameter:} \\
\hline
{\tt type} & {\it string} & type of the PyLCM object that will be created. $=$ {\tt LCM}
object {\sc lcm} in memory; $=$ {\tt XSM} persistent object of type {\sc xsm}; $=$ {\tt BINARY}
binary sequential file; $=$ {\tt ASCII}; sequential file {\sc ascii};
$=$ {\tt DA}; direct access file; $=$ {\tt HDF5}; HDF5 file; $=$ {\tt LCM\_IMP}
object {\sc lcm} in memory built from the file "{\tt \_}"$ + $ {\tt name} containing
a serialized PyLCM object or from a deep copy of object {\tt pyobj}; $=$ {\tt XSM\_INP} persistent object of type {\sc xsm} built
from the file "{\tt \_}"$ + $ {\tt name} containing a serialized PyLCM object or from a deep copy of object {\tt pyobj}. \\
{\tt name} & {\it string} & name (len=72) of the PyLCM object that will be created. By default, a name is generated automatically
from the address of the PyLCM object or from the name of object {\tt pyobj}. \\
{\tt iact} & {\it int} &access mode. $=0$: a new object is created (default); $=1$: existing object content open in read/write mode
                               $=$2: existing object content open in read-only mode. \\
{\tt pyobj} & {\it LCM} & existing PyLCM object containing a memory or persistent LCM object. \\
{\tt lrda} & {\it int}  & number of words in a direct-access record
(only used if {\tt type} $ = $ {\tt DA}). By default, {\tt lrda} $= 128$. \\
{\tt impx} & {\it int}  & edition index for the object ($=0$ for minimum printouts). \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt o} & {\it LCM} & PyLCM object created. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.keys()}

This method allows you to create a Python list containing the key names of the associative table
(memory or {\sc xsm} file). This method is not available for FILE objects.

\begin{verbatim}
o2 = o.keys()
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt o2} & {\it list} & Python list containing the keys of the associative table. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.lib()}

This method allows you to print the table-of-contents of a PyLCM object  (memory or {\sc xsm} file). This method is not available for
FILE objects.

\vskip 0.4cm

\subsubsection{o.val()}

This method allows you to validate the content of a PyLCM object (memory or {\sc xsm} file). This method is not available for
FILE objects.

\vskip 0.4cm

\subsubsection{o.len()}

This method returns the lenght of the active directory in a PyLCM object (memory or {\sc xsm} file). This method is not available for FILE objects.

\begin{verbatim}
length = o.len()
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt lenght} & {\it int} & length of the heterogeneous list; equal to $-1$ if the active directory is an associative table. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.rep()}

This method allows you to create an daughter associative table in the associative table (dictionary) or the list {\tt o}. This method is not available for
FILE objects.

\begin{verbatim}
[o2 =] o.rep({key | iset})
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameters:} \\
\hline
{\tt key} & {\it string} & if {\tt o} is a table; compulsory string (len $=12$) corresponding to the key of the daughter associative table \\
\hline
{\tt iset} & {\it int} & if {\tt o} is a list; index in the list {\tt o} where we find
the daughter associative table. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt o2} & {\it LCM} & daughter associative table. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.lis()}

This method allows you to create a nested child list in the associative table (dictionary) or
the {\tt o} list. The first element of the child list is located at index [0].
This method is not available for FILE objects.

\begin{verbatim}
[o2 =] o.lis({key | iset}, ilong)
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameters:} \\
\hline
{\tt key} & {\it string} & if {\tt o} is a table; compulsory string (len $=12$) corresponding to the key
from the daughter list. \\
\hline
{\tt iset} & {\it int} & if {\tt o} is a list; index in the list {\tt o} where we find the list daughter list. \\
\hline
{\tt ilong} & {\it int} & positive integer (required) which gives the length of the list daughter list. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt o2} & {\it LCM} & daughter list. \\
\hline
\end{tabular}

\section{The Python3 CLE-2000 API}

The Python3 CLE-2000 API is a component of the PyGAN library, available in the Version5 distribution. It contains two extension modules, each of them containing a class: {\sc lifo} and {\sc cle2000}, both implemented using the CLE-2000 API of Sect.~\ref{sect:cle2000apiC}. 

\subsection{The lifo class}

The {\sc lifo} extension module allows {\sl in-out} access to the {\sc lifo} objects ("last in first out" stack) used by CLE-2000.

The {\tt lifo} module, accessible from Python3, is imported by the command
\begin{verbatim}
import lifo
\end{verbatim}
It has one constructor: {\tt lifo.new()}, used to create an {\sl object instance} {\tt o}.

\subsubsection{Attribute Variables \index {attribute variables}}

A {\sc lifo} object {\tt o} contains one read-write attribute variable:

\begin {description}
\item [{\tt o.\_impx}] Edition index for the object ($=0$ for minimum printouts).
\end {description}

\subsubsection{lifo.new()}

This method is used to create a {\sc lifo} object made up of an empty stack. A {\sc lifo} stack is a memory-resident structure
implemented with the CLE-2000 API of Sect.~\ref{sect:cle2000apiC}. 

\begin{verbatim}
o = lifo.new([impx])
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameter:} \\
\hline
{\tt impx} & {\it int}  & edition index for the object ($=0$ for minimum printouts). \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt o} & {\it LIFO} & {\sc lifo} object created. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.lib()}

This method allows you to print the table-of-contents of a {\sc lifo} object.

\begin{verbatim}
o.lib()
\end{verbatim}

\vskip 0.4cm

\subsubsection{o.push()}

This method is used to push a new node into the {\sc lifo} object. The new node is a Python3 object of specific type. Empty nodes have defined names and types but no assigned value.  The number of nodes stored in the {\sc lifo} object is increased by one.

\begin{verbatim}
o.push(data)
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameter:} \\
\hline
{\tt data} & {\it object}  & Python3 object to push in the stack. The following Python3 types are allowed: integer variable (int), character string (str), double-precision variable (float),
logical variable (bool),  PyLCM object, empty variable of type int, str, float or bool.\\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.pushEmpty()}

This method is used to push an empty node into the {\sc lifo} object. Empty nodes have defined names and types but no assigned value. The number of nodes stored in the {\sc lifo} object is increased by one.

\begin{verbatim}
o.pushEmpty(OSname, [type])
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameter:} \\
\hline
{\tt OSname} &  {\it string}  & character (len=72) OSname of the empty node. Used to name the PyLCM object. \\
{\tt type} & {\it string}  & character type of the empty object to push in the stack. The following character types are allowed: ``{\tt I}'': integer variable, ``{\tt S}'': character string, ``{\tt D}'': double precision variable, ``{\tt B}'':
logical variable, ``{\tt LCM}'': PyLCM object of type {\sc lcm}, ``{\tt XSM}'': PyLCM object of type {\sc xsm}, ``{\tt BINARY}'': PyLCM object containing a sequential binary file,  ``{\tt ASCII}'': PyLCM object containing a sqquential {\sc ascii} file, 
``{\tt DA}'': PyLCM object containing a direct access file, ``{\tt HDF5}'': PyLCM object containing a HDF5 file. By default, {\tt type} $=$ ``{\tt LCM}''.\\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.pop()}

This method is used to pop a node from the {\sc lifo} object. The number of nodes stored in the {\sc lifo} object is decreased by one.

\begin{verbatim}
[obj =] o.pop()
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt obj} & {\it object} & Python3 object contained in the node. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.node()}

This method is used to recover a node from the {\sc lifo} object without changing its content. The number of nodes stored in the {\sc lifo} object is left unchanged.

\begin{verbatim}
obj = o.node({ ipos | name })
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameter:} \\
\hline
{\tt ipos} & {\it int}  & position of the node in the stack (the first node is at position 0). \\
{\tt name} & {\it string}  & OSname (len=72) of the node in the stack. \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt obj} & {\it object} & Python3 object contained in the node. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.getMax()}

This method returns the number of nodes in a {\sc lifo} object.

\begin{verbatim}
length = o.getMax()
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt lenght} & {\it int} & number of nodes in the {\sc lifo} object.\\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.OSname()}

This method returns the OSname of a node.

\begin{verbatim}
OSname = o.OSname(ipos)
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameter:} \\
\hline
{\tt ipos} & {\it int}  & position of the node in the stack (the first node is at position 0). \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt OSname} & {\it string} & OSname (len=72) of the node.\\
\hline
\end{tabular}

\subsection{The cle2000 class}

The  {\sc cle2000} extension module allows to encapsulate Ganlib5, Trivac5, Dragon5 or Donjon5 {\sl and} to execute a CLE-2000 procedure, itself calling modules of these codes or sub-CLE-2000 procedures. This extension module is based on the CLE-2000 API of Sect.~\ref{sect:cle2000apiC}. 

The {\tt cle2000} module, accessible from Python3, is imported by the command
\begin{verbatim}
import cle2000
\end{verbatim}
It has one constructor: {\tt cle2000.new()}, used to create an {\sl object instance} {\tt o}.

\subsubsection{Attribute Variables}

A {\sc cle2000} object {\tt o} contains one read-write attribute variable:

\begin {description}
\item [{\tt o.\_impx}] Edition index for the object ($=0$ for minimum printouts).
\end {description}

\subsubsection{cle2000.new()}

This method is used to create a {\sc cle2000} object including an {\tt exec()} method for executing a CLE-2000 specific procedure. 

\begin{verbatim}
o = cle2000.new(procname, olifo, [impx])
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameter:} \\
\hline
{\tt procname} & {\it string}  & name (len=12) of the CLE-2000 procedure. The OS filename of the procedure is {\tt procname} $+$  ``{\tt .c2m}'' \\
{\tt olifo} & {\it LIFO}  &{\sc lifo} object containing the procedure parameters. The {\sc lifo} object can be empty at construction time and can be filled before the call to the {\tt exec()} method.\\
{\tt impx} & {\it int}  & edition index for the object ($=0$ for minimum printouts). \\
\hline
\end{tabular}

\vskip 0.8cm

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt o} & {\it CLE2000} & {\sc cle2000} object created. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.exec()}

This method execute the procedure.

\begin{verbatim}
o.exec()
\end{verbatim}

\vskip 0.4cm

\subsubsection{o.getLifo()}

This method returns the {\sl lifo} stack containing the procedure parameters.

\begin{verbatim}
olifo = o.getLifo()
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf output parameter:} \\
\hline
{\tt olifo} & {\it LIFO}  & {\sc lifo} object. \\
\hline
\end{tabular}

\vskip 0.4cm

\subsubsection{o.putLifo()}

This method put a new {\sc lifo} stack in the procedure.

\begin{verbatim}
o.putLifo(olifo)
\end{verbatim}

\noindent
\begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |}
\hline
\multicolumn {3} {| c |} {\bf input parameter:} \\
\hline
{\tt olifo} & {\it LIFO}  & {\sc lifo} object. \\
\hline
\end{tabular}
