.. ======================================================================
   CHLone - CGNS HDF5 LIBRARY only node edition
   See license.txt in the root directory of this source release
   ----------------------------------------------------------------------
   $Release:  $
   ====================================================================== 

Interfaces
==========

*CHLone* is a library, there is no tool, no application.
Three levels of interfaces are available in CHLone, **C1** is the higher level,
it is the *CGNS MLL Clone* same API as CGNS/MLL with a different implementation
**F2** the *Fortran Facilities*, an interface designed for Fortran users,
**L3** the *Low Level Library*, manages HDF5 nodes.

*CHLone* also includes its own Python interface, it is not an API but rather
an translator from/to `CGNS/Python`. Two functions, `load` and `save`, provide
the user with a simple but versatile entry door for CGNS data manipulation 
in Python.
See :ref:`python CHLone module <pythonCHLone>`.

.. image:: ./images/libstack.png
   :width: 16cm
   :align: center

The schema above shows the relationships between the three `CHLone`
interfaces and the existing application . The **L3** is the node management,
all other interfaces are built on top of it.
The **SIDS-to-Python** interface offers a Python module so-called ``CHLone``, 
which can load/save *CGNS/Python* complete trees as lists of lists, containing
plain strings or `numpy` arrays.
The **F2** is for Fortran users but actually has a C interface as well,
nodes are selected and manipulated by means of their paths.
The **C1** is built to provide the user with exactely the same interface
as *CGNS/MLL*, thus allowing the user to change its *CGNS* implementation
with a simple relink of his programs.

.. _l3interface:

L3 interface
++++++++++++

The L3 interface is the *Low Level Library*.  
It is not intend to be used by developpers, the target CHLone
interfaces are F2 and SIDS-to-Python, the C1 interface is
of lower priority. 

The CGNS data structure is based on a tree. Each node can contain a
value and may have a set of children. The basic data structure of L3
is this node, in the L3 interface you can find function to handle the
data of this node and to parse its children.

Each L3 function handles only one L3 node. The access to
the target file is performed using a context, it is a required
argument to all L3 functions. The L3 node itself is a C structure used to
gather all the required arguments for an L3 function call. Each call
actually read/writes data in/from `HDF5`, there is no data buffering.
The actual data pointer, for example for a *coordinates array* can be
a new pointer coming from the L3 layer or an existing pointer passed
as an argument to the L3 layer. This actual pointer is the one used by
the `HDF5` calls, then there is no memory copy or buffering, which is
helpfull when you are dealing with very large amount of data.


Open and close a context
------------------------

The `L3_openFile` function is the first you call. It returns a context
you should give as argument to the forthcoming L3 calls. You close or
free a context using ``L3_close`` function.

.. highlight:: c

.. code-block:: c

  L3_Cursor_t *cgnsfile;

  cgnsfile=L3_openFile("M6wing.cgns",L3E_OPEN_NEW,L3F_OPEN_DEFAULT);
  L3_close(cgnsfile);

The second argument indicates if the open has to create a new file or
has to open an previously created file (or a so-called 'old'
file). You can open an existing file using the ``L3E_OPEN_OLD`` flag
instead of ``L3E_OPEN_NEW`` . If you try to access an 'old' file using
the new flag, or to create a 'new' file without the new flag, an error
occurs. The open function returns a ``NULL`` context if an error
occurs. Please,
refer to section about :ref:`error <l3errors>` management to know 
how to detect and get 
more about errors. All subsequent L3 calls using
a ``NULL`` context with return without complaining, only the first error
found is kept.

A simple way to test if an error occurs is to use the ``L3M_ECHECK``
macro, which returns 1 if there is NO error. You can also print it, if
you use to the standard output, with the `printError` function::

  L3_printError(cgnsfile);

The context can be created using ``L3_openHID``. The function uses an
existing ``hid_t`` as root id or the CGNS tree, then you don't need to
provide a filename to read or write a *CGNS/HDF5* tree, you just have
to find an HDF5 object acting as a root of your tree.
The user has to check if the ``hid_t`` can be used for such a purpose. 
For example, you can open an in-memory HDF5 or even have your own HDF5 driver::

  L3_Context_t *cgnstree;
  cgnstree=L3_openHID(rootid);

The ``L3_close`` has no action on such a rootid. All the L3 functions
will accept the context without restriction on the way you get the
actual root id.

Create and delete a node
------------------------

Once you have a context, you can manage the nodes. We mean the *L3 node*,
not the actual HDF5 node. In practice, these nodes very close but we need
an intermediate structure in L3 to hide some implemention details and
to make the user believe its node is a CGNS low level node.

An actual node is
identified with its ID, of type ``hid_t``. This ID is the HDF5 ID, you can
also use it for any HDF5 API call. The root id of the current context
you have is stored in the root_id member of your context. The way to
create, read or update a node is to use a ``L3_Node_t`` descriptor. The
contents of a node is always the same, whichever type of CGNS SIDS
node it is. The table below shows this contents.

 +---------------+-------------------------+-------------+
 | **Attribute** | **Type** 	           | **Remark**  |
 +===============+=========================+=============+
 | ``name``      | *string* 	           | \(1)        |
 +---------------+-------------------------+-------------+
 | ``label``     | *string*                | \(2)        |
 +---------------+-------------------------+-------------+
 | ``dimensions``| *array of integers*     |             |
 +---------------+-------------------------+-------------+
 | ``datatype``  | *string*                | \(3)        |
 +---------------+-------------------------+-------------+
 | ``data``      | *depends on datatype*   | \(4)        |
 +---------------+-------------------------+-------------+
 | ``flags``     | *integer*               | \(5)        |
 +---------------+-------------------------+-------------+

**Remarks:**

**1** *Name of the node* The name can have any ASCII char  
except the ``[/]`` <slash> and the ``[>]`` <greater than>. 
The first is used to separate node names in a path, the second is
internally used by *CGNS/HDF5* for the symbolic links.
The ``[ ]`` <space> and ``[.]`` <dot> are 
allowed except as the first character of the name.

**2** *CGNS/SIDS type of the node* 
Usually it is a capitalized string with the ``[_t]`` postfix.

**3** *CGNS/SIDS type of the data in the node*
The CGNS/SIDS datatypes are:

   * ``C1`` a string (that is an array of characters, the array should not contain a trailing ``[\0]``).
   * ``I4``, ``I8`` integer and long integer
   * ``R4``, ``R8`` float and double float.

**4** *Actual data* A contiguous array of data using the 
so-called *Fortran* indexing

**5** *A bitfields as an integer* The value ``0x0001``
indicates that the FORTRAN flag is set. In that case, the node has been 
written using the MLL library. See section The ``L3_Node_t`` structure 
has other attributes, see section implementation remarks about these.

All the CGNS/SIDS types and some names of its annex A have
constants. The names are postfixed with ``[_n]`` and the types with
``[_ts]``. The next code snippet shows a call to ``L3_nodeSet``. It returns a
new pointer to a ``L3_Node_t`` structure with the arguments::

  L3_Context_t cgnsfile;
  L3_Node_t node;
  int dims[2]={1,-1};

  node=L3_nodeSet(cgnsfile,NULL,
		  CGNSLibraryVersion_n,CGNSLibraryVersion_ts,dims,L3E_R4,data)

The first argument is the context, the second is the ``L3_Node_t`` where
to set the values. In that case, we pass ``NULL``, this means we have no
``L3_Node_t`` to set, we want a new one. In all cases, the returned
pointer is the ``L3_Node_t`` that has been set.  The arguments 3 and 4 are
the name and the label of the node, here we set the ``CGNSLibraryVersion``
node. Then comes the dimensions of the data and its type, here we have
a single one float. The data itself, the last argument, is the float.
The dimensions are stored into an integer array, it is read until it
reaches a -1 value, indicating that the rest of the data is not
relevant.  Now we can create an actual CGNS/HDF5 node, we use the
``L3_nodeCreate`` fonction::

  hid_t cgnslibraryversion;

  cgnslibraryversion=L3_nodeCreate(cgnsfile,cgnsfile->root_id,node);

The first argument is the context, the second one is the parent of the
node to create, in that case we use the context to get the root ID of
the current file. The returned value is the new CGNS/HDF5 node ID.
This two steps creation is useful when you have a lot of similar nodes
to create, or when you want to update. The example hereafter shows an
incomplete example for the creation of some CGNS zones with the same
dimensions. The ``NULL`` arguments passed to ``L3_nodeSet`` let the previous
value of the node unchanged::

  node=L3_nodeSet(cgnsfile,NULL,NULL, Zone_ts,dims,L3E_I4,data);
  L3_nodeCreate(cgnsfile,base,L3_nodeSet(db,node,"Zone-001",NULL,NULL,NULL,NULL));
  L3_nodeCreate(cgnsfile,base,L3_nodeSet(db,node,"Zone-002",NULL,NULL,NULL,NULL));
  L3_nodeCreate(cgnsfile,base,L3_nodeSet(db,node,"Zone-003",NULL,NULL,NULL,NULL));

The deletion of a node requires its parent ID and its name, no ``L3_Node_t``::

  L3_nodeDelete(cgnsfile,base,"Zone-003");

The deletion is performed by the HDF5 library, all children nodes are
recursively deleted.

Find and modify a node
----------------------

The ``L3_Node_t`` has been filled with data to create a new node. You can
also use this structure to update an existing node. First, you have to
retrieve the information of an HD5 object and fill the ``L3_Node_t`` node
with it::

  L3_Context_t *cgnsfile;
  L3_Node_t    *node;
  hid_t         id;

  node=L3_nodeRetrieve(cgnsfile,id);

The ``L3_Node_t`` node found contains its name, label, dimensions and
data, these are all the data used for creation.  You can display a
node content on the standard output using the ``L3_nodePrint``. The output
is limited to the name, the label and the data type::

  L3_nodePrint(node);

The node contains more thant these data. For example, the list of
children Ids are also stored into the ``L3_Node_t``. You can loop on this
list, you have to use the children attribute of the returned
``L3_Node_t``, it is an array of ``hid_t`` Ids, one per actual child. The list
ends with a -1 value instead of a valid hid_t::

  L3_Node_t    *childnode;

  node=L3_nodeRetrieve(cgnsfile,id);
  while ((node->children != NULL) && (node->children[n] != -1))
  {
    childnode=L3_nodeRetrieve(cgnsfile,rode->children[n]));
    n++;
  } 

The ``L3_Node_t`` you get using the ``L3_nodeRetrieve`` also has the ID you
used to retrieve it. You have not this information in a ``L3_Node_t`` you
created with ``L3_nodeSet``. You can change the values in this ``L3_Node_t``
in order to update the HDF5 object::
  
  L3_nodeSet(cgnsfile,node,"New Name",NULL,NULL,NULL,NULL);
  L3_nodeUpdate(cgnsfile,node);

The ID is not an argument of the function, it is in the ``L3_Node_t``
structure. The example above acts like a rename of the HDF5 object. A
simple rename, not a move, in other words the parent HDF5 object is
unchanged. If you intend to move your node, that is to change its
father, you have to use the ``L3_nodeMove`` function::

  L3_nodeMove(cgnsfile,parentid,newparentid,"name","newname");

The first argument is the context, the second is the current parent of
the node to move. The third is the new parent of the node. The two
last strings are the current name and the new name.  You can also
update a C variable with the contents of an existing ``L3_Node_t``. The
``L3_nodeGet`` function takes C variables as arguments, these are updated
with the values found in the ``L3_Node_t`` structure::

  int dims[L3_MAX_DIMS];

  node=L3_nodeRetrieve(cgnsfile,id);
  L3_nodeGet(cgnsfile,node,NULL,NULL,dims,NULL,NULL);

The ``L3_nodeFind`` function looks for a child node starting from a given
HDF5 object. The returned value is a hid_t not a ``L3_Node_t``. The third
argument of the find is a path defined as the classical string.  The
example hereafter shows the composition of L3 function calls, used to
get an ``hid_t`` and then to fill the ``L3_Node_t``::

  L3_nodeRetrieve(cgnsfile,L3_nodeFind(cgnsfile,id,"./Zone-001/ZoneBC"))

Links
-----

The CGNS link is more or less like the UNIX file system symbolic
link. An HDF5 object refers to another object, that can be in the same
ile or into another file. When you access to this object, it is up to
HDF5 library to follow the link and let you believe that you are
accessing the linked-to object instead of the current object. The
policies related to linked-to files are detailled in You may want to
detect if a node is a link, for example if you do not want to parse
some files The creation of such an HDF5 object is performed with the
``L3_nodeLink`` function::

  zoneid=L3_nodeFind(cgnsfile,cgnsfile->root_id,"/Base-02/Zone-001")
  L3_nodeLink(cgnsfile,zoneid,"GridCoordinates",
              "M6wing.cgns","/Base-01/Zone-001/Grid#01");

In this former example, the zone ID is found using ``L3_nodeFind``. A link
is made from the current file to another file, the local name is
``GridCoordinates`` and the linked-to node is identified by a path.  An
important point to know is that you do not need to open the
destination file. The destination file and the destination node may
exist or not, the error will only occur when you try to access to the
HDF5 object. If you want to be sure your linked-to file and node
exist, you can set the ``L3F_FAILSONLINK`` flag.  The ``L3F_FOLLOWLINKS`` is
set by default, you have to set it to alse if you want to detect links
before the HDF5 library automatically jumps to the linked-to object.

Other functions
---------------

You can get the HDF5 id of a object using its path and retrieve the
path of an object giving its HDF5 id. The two functions are
``L3_path2Node`` and ``L3_node2Path``.  The ``L3_isSameNode`` unction checks
wether to ``hid_t`` are refering to the same HDF5 actual object.  The two
functions ``L3_typeAsStr`` and ``L3_typeAsEnum`` are used to translate the
HDF5 data type into the L3 string or the L3 enumerate.  Some
convenience functions are used to initialize or set dimensions and
data::

  L3_initDims(dims,3,3,-1);
  data=L3_initData(dims,data,L3E_I4,9,3,5,8,2,4,0,0,0);
  data=L3_fillData(dims,data,L3E_I4,0);

About flags
-----------

The flags are an important topic of the L3 interface. The behavior of
the interface can be changed just by setting or unsetting one
flag. The flags are associated with the context, each L3 function
looks at the context flags, so that you can change flags between two
function calls. You can change the flags using the ``L3_setFlags`` and
retrieve them with ``L3_getFlags``. A set of macros are useful, the
L3M_HASFLAG, L3M_SETFLAG and L3M_UNSETFLAG.

 +-----------------------+-----------------------------------------------+---+
 |  **Flag**             | **Usage**                                     |   |
 +=======================+===============================================+===+
 | ``L3F_NONE``          | All flags set to False                        | x |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_NULL``          | Unsignificant flags value                     | x |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_WITHDATA``      | Load/Save DataArray_t                         | 1 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_WITHCHILDREN``  | Add children in the process, not recursive    | 1 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_FAILSONLINK``   | Raises an error if the link is not reachable  | 1 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_FOLLOWLINKS``   | Traverse the link and continue the process    | 1 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_MERGELINKS``    | Reserved                                      | 0 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_COMPRESS``      | Compress DataArray_t                          | 0 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_SKIPONERROR``   | First error forces skip of following L3 calls | 1 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_OWNDATA``       | Reserved                                      | 0 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_NOCHILDMERGE``  | Reserved                                      | 0 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_WITHLINKINFO``  | Reserved                                      | 0 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_WITHMUTEX``     | Use the mutual exclusion locks                | 1 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_FILLNANDATA``   | Fill created DataArray_t with NaN             | 1 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_BULLETPROOF``   | Force checks on args and functions returns    | 0 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_HASEXTFLAGS``   | Extension flags are present                   | 0 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_DEBUG``         | Verbose trace with internal data debug        | 0 |
 +-----------------------+-----------------------------------------------+---+
 | ``L3F_TRACE``         | End-user trace                                | 0 |
 +-----------------------+-----------------------------------------------+---+

A flag is an integer. The default flags are set using the L3F_DEFAULT
value, which sets::

  L3F_FOLLOWLINKS|L3F_WITHDATA|L3F_WITHMUTEX|L3F_WITHCHILDREN|L3F_SKIPONERROR

.. _l3errors:


Error management
----------------

CHLone defines its own set of error codes. The L3 interface, which is
the closest to HDF5 calls, traps the HDF5 errors and translates them
in CHLone codes. You can ask to CHLone to let HDF5 error stack appear
if you set the TRACE flag.  The error functions of the CHLone
interface are::

  void   CHL_printError (L3_Cursor_t *ctxt);
  void   CHL_setError   (L3_Cursor_t *ctxt, int err, ...);
  int    CHL_getError   (L3_Cursor_t *ctxt);
  int    CHL_setMessage (L3_Cursor_t* ctxt,char *msg);
  char  *CHL_getMessage (L3_Cursor_t* ctxt);

If you want a more detailled explanation of what an error code means,
you can refer to the table in annex.

Interface summary
-----------------

The interface contents with all enumarates, macros, functions, error codes.

.. toctree::
   :maxdepth: 1

   l3

.. _f2interface:

F2 interface
++++++++++++

The F2 interface is a node-based interface with fortran oriented functions.
The user application parses a CGNS/HDF5 tree by means of paths, it stores
selected paths in stacks and access to nodes using both stack or paths.
The node is the actual data the application wants, a node may contain an
array and F2 provides node array manipulation too.

The parsing of a tree is an extra processing added to usual applications.
The application can performs F2 node selections using path-based functions.
A set of paths can be extracted from a complete tree with respect to a
pattern including specific tokens such as plain node name, plain node type or
even regular expressions. See the section about path querying hereafter.

.. note:
   The F2 fortran functions are a direct mapping of F2 C functions. Then
   the F2 API is available in Fortran as well as in C langage. 

+--------+-------------------------------------------------------------------+
| Entity | Purpose                                                           |
+========+===================================================================+
| ID     | A CGNS/HDF5 node as a unique identifier (the HDF5 `hid_t`). This  |
|        | ID is a key to a node as well as the Path.                        |
+--------+-------------------------------------------------------------------+
| Path   | A string that identify a node in a CGNS/HDF5 tree. The Path is a  |
|        | suite of `token`s separated by the `/` character.                 |
+--------+-------------------------------------------------------------------+
| Token  | A node name, this string may not be unique in all the CGNS/HDF5   |
|        | tree.                                                             |
+--------+-------------------------------------------------------------------+
| Stack  | An ordered list of `Path`s, used for application purpose. For     |
|        | example you store the X,Y and Z coordinate nodes' paths in a      |
|        | stack and you manipulate the stack as a whole instead of each     |
|        | node.                                                             |
+--------+-------------------------------------------------------------------+

The interface use is then to define or to find out paths, to
get corresponding IDs and to call functions with these IDs as arguments.
For example, you want to get dimensions for all structured zones in a base.

.. code-block:: fortran

  F=1
  S=1
  path="/CGNSTree_t/Base#01/Zone_t/ZoneType_t"
  nzones=f2_stackFetchByString(F,S,path,"Structured")
  do n=1,nzones
    f2_nodeDimensions(F,f2_stackParentId(F,S,n))
  enddo

  S=2
  path="/CGNSTree_t/Base#01/Zone_t/GridCoordinates/^Coordinates[XYZ]$"
  ncoords=f2_stackFetch(F,S,path)
  f2_arrayAsContiguous(F,path,T)

Context
-------

A ``Context`` is more or less a CGNS/HDF5 file. It could be more in the case
of links, but we approximate here as one context is one file. 
Most F2 functions do require a context as first argument, then the first
function you have to call is the ``F2_open_f`` which opens a context related
to the given filename. The returned value ``C`` is the index of the context 
in the F2 internal tables.

.. code-block:: fortran

  integer C

  call F2_open_f("/tmp/file.cgns",1,-1,C)
  call F2_close_f(C) 

The remaining arguments are unused here, the first 1 is the flags and the -1
is the root id. You can have more than one context, and opening, using and
closing a context is thread-safe. 

.. _pathpattern:

Paths and Stacks
----------------

A path is a string used to identify a node in a CGNS tree.
The path syntax is the same as the Unix file system syntax, and obviously
the same as the HDF5 syntax. 

.. note::
   The path we use in CHLone is different to the HDF5 node path as 
   we have the root node, ``CGNSTree`` of type ``CGNSTree_t``.
   If you remove this first token of the path, you actually have the HDF5 path.

A path is composed of tokens separated by the `/` char. A token can be 
a plain name token, a plain type token or a regular expression token.

A *plain name token* is a token used to select a node name matches exactly the
characters. 

A *plain type token* is a token used to select a node *SIDS type* instead of its
name. For example `GridCoordinates_t` can be used to match all nodes having
this string as *SIDS type*. The token should have ``_t`` as the two last
characters to make CHLone detect it is a SIDS type token.

A *regular expression token* is a used to select node names given a
regular expression. The first character should be a ``^`` and the last
should be ``$``, this is the way CHLone detects a regular expression token
to the other token types.

The examples hereafter show usual patterns used for a CGNS tree parsing.
Some paths may represent a set of paths instead of a single one,
we use the term `matches` to say a node actually belong to the set
defined by the path.

A plain path, all tokens are plain tokens. Then it should lead to a single
node, here it matchesThe X coordinates of the zone `D.001` in the base `Flap`.

.. code-block:: shell

  /CGNSTree/Flap/D.001/GridCoordinates/CoordinatesX

A path with both a type selection and a regular expression. The third
token ``Zone_t`` defines the type of the node rather than its name.
Then all nodes with the SIDS type ``Zone_t`` would match. The last token
is a regular expression, enclosed by ``^`` and ``$``, that defines a plain
string ``Coordinates`` and a set of possible characters ``X``,``Y`` or ``Z``.
All X,Y and Z coordinates would match this token. The result of the path
search in a CGNS tree is all the coordinates of all the zones 
of the base `Flap`.

.. code-block:: shell

 /CGNSTree/Flap/Zone_t/GridCoordinates/^Coordinates[XYZ]$

When the result contains more then one path it needs to be stored in a list.
The F2 interface defines **stacks** for that purpose. All the returning path,
even if there is only one, is stored in the stack. You can use the stack
for operations on a set of nodes instead of a single one.

A stack is identified by an integer index. You can have many stacks, you have
to select the stack you operate on by specifying its index. In the exemple
hereafter, ``C`` is the context and ``S`` is the stack.

.. code-block:: fortran

  integer C,S

  S=1
  path="/CGNSTree/Flap/Zone_t/GridCoordinates/^Coordinates[XYZ]$"

  call F2_open_f("/tmp/file.cgns",1,-1,C)
  call F2_stackClear(C,S)
  call F2_stackFetch(C,S,path)
  call F2_close_f(C)

You have to retrieve the actual node from its path if you want to
operate on its data.

Errors
------

Interface summary
-----------------

The interface contents with all enumarates, macros, functions, error codes.

.. toctree::
   :maxdepth: 1

   f2

.. _c1interface:

C1 interface
++++++++++++

The C1 interface is the exact copy (or clone) of the *CGNS/MLL* interface.
The file ``cgnslib.h`` provided by CHLone is a copy of the original file
with an add include to the ``CHLone.h`` header.
The *CHLone* interface defines the ``CHLONE_IMPLEMENTATION``, so that you can
detect at preprocessing time wether you are including the original or the clone.

CHLone vs CGNS/MLL
------------------

The *CGNS/MLL* stores the actual node ids and returns its own
indexes. CHLone returns the actual node id.  The CGNS/MLL buffers the
data, it creates its own data structure as a copy of the CGNS tree you
have on disk. Check operations are performed on the buffered
data. CHLone calls actually read/write the data on/to disk.

.. warning::
   The *C1* interface is not ready to use today.

Compatibility
-------------

The interface is 100% compatible. This means you can recompile your *CGNS/MLL*
application without modification and obtain the same results.
The CHLone lib has, however, a different implementation. If your application 
uses some *CGNS/MLL* tricks based on the legacy implementation, the change to
CHLone may result in changes in your results. In particular if you bet on
indexes returnd by *CGNS/MLL*.


Interface summary
-----------------

The C1 interface does not cover 100% of the *CGNS/MLL* interface. The reason
it is so is that the *CGNS/Python* interface is far more used by CHLone users.
Then the effort is, today, focused on the CHLone python module.

The implemented functions, as of v0.47 of CHLone, are:

 -  cg_open
 -  cg_close
 -  cg_nbases
 -  cg_base_read
 -  cg_base_write
 -  cg_zone_write
 -  cg_zone_type
 -  cg_zone_read
 -  cg_nzones
 -  cg_ncoords
 -  cg_coord_info
 -  cg_coord_read
 -  cg_coord_write


.. toctree::
   :maxdepth: 1

   c1