\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} \vskip 0.8cm \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} \vskip 0.8cm \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; =3 erase and close the LCM object without 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} \vskip 0.8cm \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} \vskip 0.8cm \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 LCM object. \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} \vskip 0.8cm \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.8cm} \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} \vskip 0.8cm \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 #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 #include #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 #include #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 :: <> >>prev_fact<< ; EVALUATE n_fact := n 1 + prev_fact * ; ENDIF ; :: <> ; QUIT " Recursive procedure *fact* XREF " . \end{verbatim} This procedure can be called from a program implemented in ANSI~C, using \begin{verbatim} #include #include #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} \vskip 0.8cm \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 #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} \vskip 0.8cm \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} \vskip 0.8cm \subsection {The free-format input reader} The free-format inpsut 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} \vskip 0.8cm \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} \vskip 0.8cm \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; =3 erase and close the LCM object without 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} \vskip 0.8cm \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); =999 undefined (999 is returned if index {\tt ISET} is out of bounds). \\ \hline \end{tabular} \vskip 0.8cm \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 LCM object. \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} \vskip 0.8cm \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.8cm} \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} \vskip 0.8cm \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 string in the array {\tt HDATA}. \\ \hline {\tt NLIN} & {\it INTEGER} & dimension of array {\tt HDATA}. This parameter is omitted if {\tt HDATA} \\ & & is a single character string. \\ \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 string in the array {\tt HDATA}. \\ \hline {\tt NLIN} & {\it INTEGER} & dimension of array {\tt HDATA}. This parameter is omitted if {\tt HDATA} \\ & & is a single character string. \\ \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 string in the array {\tt HDATA}. \\ \hline {\tt NLIN} & {\it INTEGER} & dimension of array {\tt HDATA}. This parameter is omitted if {\tt HDATA} \\ & & is a single character string. \\ \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 string in the array {\tt HDATA}. \\ \hline {\tt NLIN} & {\it INTEGER} & dimension of array {\tt HDATA}. This parameter is omitted if {\tt HDATA} \\ & & is a single character string. \\ \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} \vskip 0.8cm \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} \vskip 0.8cm \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} \vskip 0.8cm \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} \vskip 0.8cm \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\_delete\index{hdf5Delete}} Delete a group or a dataset. \begin{verbatim} call hdf5_delete(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 or dataset to delete. \\ \hline \end{tabular} \vskip 0.8cm \subsubsection{hdf5\_copy\index{hdf5Copy}} Copy a group or a dataset from one location to another. The source and destination need not be in the same file. \begin{verbatim} call hdf5_copy(ifile_s, name_s, ifile_d, name_d) \end{verbatim} \noindent \begin{tabular}{|p{1.5cm}|p{3cm}|p{10cm}|} \hline \multicolumn{3}{|c|}{\bf input parameters:} \\ \hline {\tt ifile\_s} & {\it type(c\_ptr)} & address of the HDF5 source file. \\ \hline {\tt name\_s} & {\it character*1023} & name of the source group or dataset to copy. \\ \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\_d} & {\it type(c\_ptr)} & address of the HDF5 destination file. \\ \hline {\tt name\_d} & {\it character*1023} & name of the destination group or dataset to delete. \\ \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. If dataset {\tt name} exists, it is replaced. \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} \vskip 0.8cm \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} \vskip 0.8cm \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} \vskip 0.8cm \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 {\tt x86\_64} 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} \noindent On a Linux {\tt aarm} operating system, the environment variable is set as \begin{verbatim} export FORTRANPATH="/usr/lib/gcc/aarch64-linux-gnu/9/" # contains libgfortran.so \end{verbatim} \vskip 0.8cm \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} \vskip 0.8cm \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} sequential binary file; $=$ {\tt ASCII}; sequential {\sc ascii} file ; $=$ {\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}. The serialized PyLCM object is assumed to be a sequential binary file if its extension is {\tt .bin}; otherwise, it is assumed to be a sequential {\sc ascii} file.\\ {\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.8cm \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.8cm \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.8cm \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.8cm \subsubsection{o.close()} This method allows you to close a PyLCM object (memory or {\sc xsm} file) without erasing its contents. This method is not available for FILE objects. \vskip 0.8cm \subsubsection{o.erase()} This method allows you to erase the contents of a PyLCM object (memory or {\sc xsm} file). \vskip 0.8cm \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.8cm \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.8cm \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}. \vskip 0.8cm \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.8cm \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.8cm \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.8cm \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(name, [type]) \end{verbatim} \noindent \begin{tabular} {| p {1.5cm} | p {1.5cm} | p {11.5cm} |} \hline \multicolumn {3} {| c |} {\bf input parameter:} \\ \hline {\tt name} & {\it string} & character (len=72) name 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.8cm \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.8cm \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} & name (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.8cm \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.8cm \subsubsection{o.OSname()} This method returns the name of a node. \begin{verbatim} name = 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 name} & {\it string} & name (len=72) of the node.\\ \hline \end{tabular} \vskip 0.8cm \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.8cm \subsubsection{o.exec()} This method execute the procedure. \begin{verbatim} o.exec() \end{verbatim} \vskip 0.8cm \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.8cm \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}