Salome HOME
HEXA_27021382: EDF 1985 SMESH: Read/write of .mesh files (GMF format)
authoreap <eap@opencascade.com>
Mon, 24 Sep 2012 11:15:01 +0000 (11:15 +0000)
committereap <eap@opencascade.com>
Mon, 24 Sep 2012 11:15:01 +0000 (11:15 +0000)
src/DriverGMF/DriverGMF_Read.cxx [new file with mode: 0644]
src/DriverGMF/DriverGMF_Read.hxx [new file with mode: 0644]
src/DriverGMF/DriverGMF_Write.cxx [new file with mode: 0644]
src/DriverGMF/DriverGMF_Write.hxx [new file with mode: 0644]
src/DriverGMF/Makefile.am [new file with mode: 0644]
src/DriverGMF/SMESH_DriverGMF.hxx [new file with mode: 0755]
src/DriverGMF/libmesh5.c [new file with mode: 0644]
src/DriverGMF/libmesh5.h [new file with mode: 0644]

diff --git a/src/DriverGMF/DriverGMF_Read.cxx b/src/DriverGMF/DriverGMF_Read.cxx
new file mode 100644 (file)
index 0000000..332519b
--- /dev/null
@@ -0,0 +1,357 @@
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, Read to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File      : DriverGMF_Read.cxx
+// Created   : Mon Sep 17 17:03:02 2012
+// Author    : Edward AGAPOV (eap)
+
+#include "DriverGMF_Read.hxx"
+#include "DriverGMF_Write.hxx"
+
+#include "SMESHDS_Group.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Comment.hxx"
+
+extern "C"
+{
+#include "libmesh5.h"
+}
+
+#include <stdarg.h>
+
+// --------------------------------------------------------------------------------
+// Closing GMF mesh at destruction
+DriverGMF_MeshCloser::~DriverGMF_MeshCloser()
+{
+  if ( _gmfMeshID )
+    GmfCloseMesh( _gmfMeshID );
+}
+// --------------------------------------------------------------------------------
+DriverGMF_Read::DriverGMF_Read():
+  Driver_SMESHDS_Mesh()
+{
+}
+// --------------------------------------------------------------------------------
+DriverGMF_Read::~DriverGMF_Read()
+{
+}
+
+//================================================================================
+/*!
+ * \brief Read a GMF file
+ */
+//================================================================================
+
+Driver_Mesh::Status DriverGMF_Read::Perform()
+{
+  Status status = DRS_OK;
+
+  int dim, version;
+
+  // open the file
+  int meshID = GmfOpenMesh( myFile.c_str(), GmfRead, &version, &dim );
+  if ( !meshID )
+    return addMessage( SMESH_Comment("Can't open for reading ") << myFile, /*fatal=*/true );
+
+  DriverGMF_MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction
+
+  // Read nodes
+
+  int nbNodes = GmfStatKwd(meshID, GmfVertices);
+  if ( nbNodes < 1 )
+    return addMessage( "No nodes in the mesh", /*fatal=*/true );
+
+  GmfGotoKwd(meshID, GmfVertices);
+
+  int ref;
+
+  const int nodeIDShift = myMesh->GetMeshInfo().NbNodes();
+  if ( version != GmfFloat )
+  {
+    double x, y, z;
+    for ( int i = 1; i <= nbNodes; ++i )
+    {
+      GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref);
+      myMesh->AddNodeWithID( x,y,z, nodeIDShift + i);
+    }
+  }
+  else
+  {
+    float x, y, z;
+    for ( int i = 1; i <= nbNodes; ++i )
+    {
+      GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref);
+      myMesh->AddNodeWithID( x,y,z, nodeIDShift + i);
+    }
+  }
+
+  // Read elements
+
+  int iN[28];
+
+  /* Read edges */
+  const int edgeIDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbEdges = GmfStatKwd(meshID, GmfEdges))
+  {
+    GmfGotoKwd(meshID, GmfEdges);
+    for ( int i = 1; i <= nbEdges; ++i )
+    {
+      GmfGetLin(meshID, GmfEdges, &iN[0], &iN[1], &ref);
+      if ( !myMesh->AddEdgeWithID( iN[0], iN[1], edgeIDShift + i ))
+        status = storeBadNodeIds( "GmfEdges",i, 2, iN[0], iN[1] );
+    }
+  }
+  /* Read quadratic edges */
+  const int edge2IDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbEdges = GmfStatKwd(meshID, GmfEdgesP2))
+  {
+    GmfGotoKwd(meshID, GmfEdgesP2);
+    for ( int i = 1; i <= nbEdges; ++i )
+    {
+      GmfGetLin(meshID, GmfEdgesP2, &iN[0], &iN[1], &iN[2], &ref);
+      if ( !myMesh->AddEdgeWithID( iN[0], iN[1], iN[2], edge2IDShift + i ))
+        status = storeBadNodeIds( "GmfEdgesP2",i, 3, iN[0], iN[1], iN[2] );
+    }
+  }
+  /* Read triangles */
+  const int triaIDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbTria = GmfStatKwd(meshID, GmfTriangles))
+  {
+    GmfGotoKwd(meshID, GmfTriangles);
+    for ( int i = 1; i <= nbTria; ++i )
+    {
+      GmfGetLin(meshID, GmfTriangles, &iN[0], &iN[1], &iN[2], &ref);
+      if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], triaIDShift + i ))
+        status = storeBadNodeIds( "GmfTriangles",i, 3, iN[0], iN[1], iN[2] );
+    }
+  }
+  /* Read quadratic triangles */
+  const int tria2IDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbTria = GmfStatKwd(meshID, GmfTrianglesP2))
+  {
+    GmfGotoKwd(meshID, GmfTrianglesP2);
+    for ( int i = 1; i <= nbTria; ++i )
+    {
+      GmfGetLin(meshID, GmfTrianglesP2,
+                &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref);
+      if ( !myMesh->AddFaceWithID( iN[0],iN[1],iN[2],iN[3],iN[4],iN[5],
+                                   tria2IDShift + i ))
+        status = storeBadNodeIds( "GmfTrianglesP2",i, 6, iN[0],iN[1],iN[2],iN[3],iN[4],iN[5] );
+    }
+  }
+  /* Read quadrangles */
+  const int quadIDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbQuad = GmfStatKwd(meshID, GmfQuadrilaterals))
+  {
+    GmfGotoKwd(meshID, GmfQuadrilaterals);
+    for ( int i = 1; i <= nbQuad; ++i )
+    {
+      GmfGetLin(meshID, GmfQuadrilaterals, &iN[0], &iN[1], &iN[2], &iN[3], &ref);
+      if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3], quadIDShift + i ))
+        status = storeBadNodeIds( "GmfQuadrilaterals",i, 4, iN[0], iN[1],iN[2], iN[3] );
+    }
+  }
+  /* Read bi-quadratic quadrangles */
+  const int quad2IDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbQuad = GmfStatKwd(meshID, GmfQuadrilateralsQ2))
+  {
+    GmfGotoKwd(meshID, GmfQuadrilateralsQ2);
+    for ( int i = 1; i <= nbQuad; ++i )
+    {
+      GmfGetLin(meshID, GmfQuadrilateralsQ2,
+                &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &iN[8], &ref);
+      if ( !myMesh->AddFaceWithID( iN[0],iN[1],iN[2],iN[3],iN[4],iN[5],iN[6],iN[7],iN[8],
+                                   quad2IDShift + i ))
+        status = storeBadNodeIds( "GmfQuadrilateralsQ2",i,
+                                  9, iN[0],iN[1],iN[2],iN[3],iN[4],iN[5],iN[6],iN[7],iN[8] );
+    }
+  }
+  /* Read terahedra */
+  const int tetIDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbTet = GmfStatKwd(meshID, GmfTetrahedra))
+  {
+    GmfGotoKwd(meshID, GmfTetrahedra);
+    for ( int i = 1; i <= nbTet; ++i )
+    {
+      GmfGetLin(meshID, GmfTetrahedra, &iN[0], &iN[1], &iN[2], &iN[3], &ref);
+      if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], tetIDShift + i ))
+        status = storeBadNodeIds( "GmfTetrahedra",i, 4, iN[0], iN[1],iN[2], iN[3] );
+    }
+  }
+  /* Read quadratic terahedra */
+  const int tet2IDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbTet = GmfStatKwd(meshID, GmfTetrahedraP2))
+  {
+    GmfGotoKwd(meshID, GmfTetrahedraP2);
+    for ( int i = 1; i <= nbTet; ++i )
+    {
+      GmfGetLin(meshID, GmfTetrahedraP2, &iN[0], &iN[1], &iN[2],
+                &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &iN[8], &iN[9], &ref);
+      if ( !myMesh->AddVolumeWithID( iN[0],iN[2],iN[1],iN[3],
+                                     iN[6],iN[5],iN[4],
+                                     iN[7],iN[9],iN[8], tet2IDShift + i ))
+        status = storeBadNodeIds( "GmfTetrahedraP2",i, 10, iN[0],iN[1],iN[2],iN[3],
+                                  iN[4],iN[5],iN[6],iN[7],iN[8],iN[9] );
+    }
+  }
+  /* Read pyramids */
+  const int pyrIDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbPyr = GmfStatKwd(meshID, GmfPyramids))
+  {
+    GmfGotoKwd(meshID, GmfPyramids);
+    for ( int i = 1; i <= nbPyr; ++i )
+    {
+      GmfGetLin(meshID, GmfPyramids, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &ref);
+      if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[4], pyrIDShift + i ))
+        status = storeBadNodeIds( "GmfPyramids",i, 5, iN[0], iN[1],iN[2], iN[3], iN[4] );
+    }
+  }
+  /* Read hexahedra */
+  const int hexIDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbHex = GmfStatKwd(meshID, GmfHexahedra))
+  {
+    GmfGotoKwd(meshID, GmfHexahedra);
+    for ( int i = 1; i <= nbHex; ++i )
+    {
+      GmfGetLin(meshID, GmfHexahedra,
+                &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &ref);
+      if ( !myMesh->AddVolumeWithID( iN[0], iN[3], iN[2], iN[1], iN[4], iN[7], iN[6], iN[5],
+                                     hexIDShift + i))
+        status = storeBadNodeIds( "GmfHexahedra",i,
+                                  8, iN[0], iN[1],iN[2], iN[3], iN[4], iN[7], iN[6], iN[5] );
+    }
+  }
+  /* Read tri-quadratic hexahedra */
+  const int hex2IDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbHex = GmfStatKwd(meshID, GmfHexahedraQ2))
+  {
+    GmfGotoKwd(meshID, GmfHexahedraQ2);
+    for ( int i = 1; i <= nbHex; ++i )
+    {
+      GmfGetLin(meshID, GmfHexahedraQ2, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5],
+                &iN[6], &iN[7], &iN[8],&iN[9],&iN[10],&iN[11],&iN[12],&iN[13],&iN[14],
+                &iN[15],&iN[16],&iN[17],&iN[18],&iN[19],&iN[20],&iN[21],&iN[22],&iN[23],
+                &iN[24],&iN[25],&iN[26], &ref);
+      if ( !myMesh->AddVolumeWithID( iN[0],iN[3],iN[2],iN[1],iN[4],iN[7],iN[6],iN[5],iN[11],iN[10],
+                                     iN[9],iN[8],iN[12],iN[15],iN[14], iN[13],iN[19],iN[18],iN[17],
+                                     iN[16],iN[20],iN[24],iN[23],iN[22],iN[21], iN[25],iN[26],
+                                     hex2IDShift + i ))
+        status = storeBadNodeIds( "GmfHexahedraQ2",i, 27,
+                                  iN[0],iN[3],iN[2],iN[1],iN[4], iN[7],iN[6],iN[5],iN[11],iN[10],
+                                  iN[9],iN[8],iN[12],iN[15],iN[14], iN[13],iN[19],iN[18],iN[17],
+                                  iN[16],iN[20],iN[24],iN[23],iN[22],iN[21], iN[25],iN[26]);
+    }
+  }
+  /* Read prism */
+  const int prismIDShift = myMesh->GetMeshInfo().NbElements();
+  if ( int nbPrism = GmfStatKwd(meshID, GmfPrisms))
+  {
+    GmfGotoKwd(meshID, GmfPrisms);
+    for ( int i = 1; i <= nbPrism; ++i )
+    {
+      GmfGetLin(meshID, GmfPrisms,
+                &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref);
+      if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[5], iN[4], prismIDShift + i))
+        status = storeBadNodeIds( "GmfPrisms",i,
+                                  6, iN[0], iN[1],iN[2], iN[3], iN[4], iN[5] );
+    }
+  }
+
+  // Read required entities into groups
+
+  // get ids of existing groups
+  std::set< int > groupIDs;
+  const std::set<SMESHDS_GroupBase*>& groups = myMesh->GetGroups();
+  std::set<SMESHDS_GroupBase*>::const_iterator grIter = groups.begin();
+  for ( ; grIter != groups.end(); ++grIter )
+    groupIDs.insert( (*grIter)->GetID() );
+  if ( groupIDs.empty() ) groupIDs.insert( 0 );
+
+  const int kes[4][3] = { { GmfRequiredVertices,      SMDSAbs_Node, nodeIDShift },
+                          { GmfRequiredEdges,         SMDSAbs_Edge, edgeIDShift },
+                          { GmfRequiredTriangles,     SMDSAbs_Face, triaIDShift },
+                          { GmfRequiredQuadrilaterals,SMDSAbs_Face, quadIDShift }};
+  const char* names[4] = { "_required_Vertices"      ,
+                           "_required_Edges"         ,
+                           "_required_Triangles"     ,
+                           "_required_Quadrilaterals" };
+  for ( int i = 0; i < 4; ++i )
+  {
+    int                 gmfKwd = kes[i][0];
+    SMDSAbs_ElementType entity = (SMDSAbs_ElementType) kes[i][1];
+    int                 shift  = kes[i][2];
+    if ( int nb = GmfStatKwd(meshID, gmfKwd))
+    {
+      const int newID = *groupIDs.rbegin() + 1;
+      groupIDs.insert( newID );
+      SMESHDS_Group* group = new SMESHDS_Group( newID, myMesh, entity );
+      group->SetStoreName( names[i] );
+      myMesh->AddGroup( group );
+
+      GmfGotoKwd(meshID, gmfKwd);
+      for ( int i = 0; i < nb; ++i )
+      {
+        GmfGetLin(meshID, gmfKwd, &iN[0] );
+        group->Add( shift + iN[0] );
+      }
+    }
+  }
+
+  return status;
+}
+
+//================================================================================
+/*!
+ * \brief Store a message about invalid IDs of nodes
+ */
+//================================================================================
+
+Driver_Mesh::Status DriverGMF_Read::storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...)
+{
+  if ( myStatus != DRS_OK )
+    return myStatus;
+
+  SMESH_Comment msg;
+
+  va_list VarArg;
+  va_start(VarArg, nb);
+
+  for ( int i = 0; i < nb; ++i )
+  {
+    int id = va_arg(VarArg, int );
+    if ( !myMesh->FindNode( id ))
+      msg << " " << id;
+  }
+  va_end(VarArg);
+
+  if ( !msg.empty() )
+  {
+    std::string nbStr;
+    const char* nbNames[] = { "1-st ", "2-nd ", "3-d " };
+    if ( elemNb < 3 ) nbStr = nbNames[ elemNb-1 ];
+    else              nbStr = SMESH_Comment(elemNb) << "-th ";
+
+    return addMessage
+      ( SMESH_Comment("Wrong node IDs of ")<< nbStr << gmfKwd << ":" << msg,
+        /*fatal=*/false );
+  }
+  return DRS_OK;
+}
diff --git a/src/DriverGMF/DriverGMF_Read.hxx b/src/DriverGMF/DriverGMF_Read.hxx
new file mode 100644 (file)
index 0000000..a003804
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, Read to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File      : DriverGMF_Read.hxx
+// Created   : Mon Sep 17 15:36:47 2012
+// Author    : Edward AGAPOV (eap)
+
+
+#ifndef __DriverGMF_Read_HXX__
+#define __DriverGMF_Read_HXX__
+
+#include "SMESH_DriverGMF.hxx"
+
+#include "Driver_SMESHDS_Mesh.h"
+
+#include <vector>
+#include <string>
+
+/*!
+ * \brief Driver reading a mesh from the GMF file. The mesh to read is selected by 
+ *  an index (counted form 0) set via SetMeshId()
+ */
+class MESHDriverGMF_EXPORT DriverGMF_Read : public Driver_SMESHDS_Mesh
+{
+public:
+
+  DriverGMF_Read();
+  ~DriverGMF_Read();
+
+  virtual Status Perform();
+
+ private:
+
+  Status storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...);
+
+};
+
+
+#endif
diff --git a/src/DriverGMF/DriverGMF_Write.cxx b/src/DriverGMF/DriverGMF_Write.cxx
new file mode 100644 (file)
index 0000000..78f414b
--- /dev/null
@@ -0,0 +1,319 @@
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File      : DriverGMF_Write.cxx
+// Created   : Mon Sep 17 17:03:02 2012
+// Author    : Edward AGAPOV (eap)
+
+#include "DriverGMF_Write.hxx"
+
+#include "SMESHDS_GroupBase.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Comment.hxx"
+
+extern "C"
+{
+#include "libmesh5.h"
+}
+
+#include <vector>
+
+#define BEGIN_ELEM_WRITE( SMDSEntity, GmfKwd, elem )                    \
+  elemIt = myMesh->elementEntityIterator( SMDSEntity );                 \
+  if ( elemIt->more() )                                                 \
+  {                                                                     \
+  GmfSetKwd(meshID, GmfKwd, myMesh->GetMeshInfo().NbEntities( SMDSEntity )); \
+  for ( int gmfID = 1; elemIt->more(); ++gmfID )                        \
+  {                                                                     \
+  const SMDS_MeshElement* elem = elemIt->next();                        \
+  GmfSetLin(meshID, GmfKwd,
+
+#define END_ELEM_WRITE( elem )                  \
+  elem->getshapeId() );                         \
+  }}                                            \
+
+#define END_ELEM_WRITE_ADD_TO_MAP( elem, e2id )         \
+  elem->getshapeId() );                                 \
+  e2id.insert( e2id.end(), make_pair( elem, gmfID ));   \
+  }}                                                    \
+
+
+DriverGMF_Write::DriverGMF_Write():
+  Driver_SMESHDS_Mesh()
+{
+}
+DriverGMF_Write::~DriverGMF_Write()
+{
+}
+
+Driver_Mesh::Status DriverGMF_Write::Perform()
+{
+  const int dim = 3, version = 3;
+
+  int meshID = GmfOpenMesh( myFile.c_str(), GmfWrite, version, dim );
+  if ( !meshID )
+    return addMessage( SMESH_Comment("Can't open for writing ") << myFile, /*fatal=*/true );
+
+  DriverGMF_MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction
+
+  // nodes
+  std::map< const SMDS_MeshNode* , int > node2IdMap;
+  int iN = 0, nbNodes = myMesh->NbNodes();
+  GmfSetKwd( meshID, GmfVertices, nbNodes );
+  double xyz[3];
+  SMDS_NodeIteratorPtr nodeIt = myMesh->nodesIterator();
+  while ( nodeIt->more() )
+  {
+    const SMDS_MeshNode* n = nodeIt->next();
+    n->GetXYZ( xyz );
+    GmfSetLin( meshID, GmfVertices, xyz[0], xyz[1], xyz[2], n->getshapeId() );
+    node2IdMap.insert( node2IdMap.end(), make_pair( n, ++iN ));
+  }
+  if ( iN != nbNodes )
+    return addMessage("Wrong nb of nodes returned by nodesIterator", /*fatal=*/true);
+
+
+  SMDS_ElemIteratorPtr elemIt;
+  typedef std::map< const SMDS_MeshElement*, size_t, TIDCompare > TElem2IDMap;
+
+  // edges
+  TElem2IDMap edge2IDMap;
+  BEGIN_ELEM_WRITE( SMDSEntity_Edge, GmfEdges, edge )
+    node2IdMap[ edge->GetNode( 0 )],
+    node2IdMap[ edge->GetNode( 1 )],
+    END_ELEM_WRITE_ADD_TO_MAP( edge, edge2IDMap );
+    
+  // quadratic edges
+  BEGIN_ELEM_WRITE( SMDSEntity_Quad_Edge, GmfEdgesP2, edge )
+    node2IdMap[ edge->GetNode( 0 )],
+    node2IdMap[ edge->GetNode( 1 )],
+    node2IdMap[ edge->GetNode( 2 )],
+    END_ELEM_WRITE( edge );
+    
+  // triangles
+  TElem2IDMap tria2IDMap;
+  BEGIN_ELEM_WRITE( SMDSEntity_Triangle, GmfTriangles, tria )
+    node2IdMap[ tria->GetNode( 0 )],
+    node2IdMap[ tria->GetNode( 1 )],
+    node2IdMap[ tria->GetNode( 2 )],
+    END_ELEM_WRITE_ADD_TO_MAP( tria, tria2IDMap );
+    
+  // quadratic triangles
+  BEGIN_ELEM_WRITE( SMDSEntity_Quad_Triangle, GmfTrianglesP2, tria )
+    node2IdMap[ tria->GetNode( 0 )],
+    node2IdMap[ tria->GetNode( 1 )],
+    node2IdMap[ tria->GetNode( 2 )],
+    node2IdMap[ tria->GetNode( 3 )],
+    node2IdMap[ tria->GetNode( 4 )],
+    node2IdMap[ tria->GetNode( 5 )],
+    END_ELEM_WRITE( tria );
+    
+  // quadrangles
+  TElem2IDMap quad2IDMap;
+  BEGIN_ELEM_WRITE( SMDSEntity_Quadrangle, GmfQuadrilaterals, quad )
+    node2IdMap[ quad->GetNode( 0 )],
+    node2IdMap[ quad->GetNode( 1 )],
+    node2IdMap[ quad->GetNode( 2 )],
+    node2IdMap[ quad->GetNode( 3 )],
+    END_ELEM_WRITE_ADD_TO_MAP( quad, quad2IDMap );
+
+  // bi-quadratic quadrangles
+  BEGIN_ELEM_WRITE( SMDSEntity_BiQuad_Quadrangle, GmfQuadrilateralsQ2, quad )
+    node2IdMap[ quad->GetNode( 0 )],
+    node2IdMap[ quad->GetNode( 3 )],
+    node2IdMap[ quad->GetNode( 2 )],
+    node2IdMap[ quad->GetNode( 1 )],
+    node2IdMap[ quad->GetNode( 7 )],
+    node2IdMap[ quad->GetNode( 6 )],
+    node2IdMap[ quad->GetNode( 5 )],
+    node2IdMap[ quad->GetNode( 4 )],
+    node2IdMap[ quad->GetNode( 8 )],
+    END_ELEM_WRITE( quad );
+    
+  // terahedra
+  BEGIN_ELEM_WRITE( SMDSEntity_Tetra, GmfTetrahedra, tetra )
+    node2IdMap[ tetra->GetNode( 0 )],
+    node2IdMap[ tetra->GetNode( 2 )],
+    node2IdMap[ tetra->GetNode( 1 )],
+    node2IdMap[ tetra->GetNode( 3 )],
+    END_ELEM_WRITE( tetra );
+    
+  // quadratic terahedra
+  BEGIN_ELEM_WRITE( SMDSEntity_Quad_Tetra, GmfTetrahedraP2, tetra )
+    node2IdMap[ tetra->GetNode( 0 )],
+    node2IdMap[ tetra->GetNode( 2 )],
+    node2IdMap[ tetra->GetNode( 1 )],
+    node2IdMap[ tetra->GetNode( 3 )],
+    node2IdMap[ tetra->GetNode( 6 )],
+    node2IdMap[ tetra->GetNode( 5 )],
+    node2IdMap[ tetra->GetNode( 4 )],
+    node2IdMap[ tetra->GetNode( 7 )],
+    node2IdMap[ tetra->GetNode( 9 )],
+    node2IdMap[ tetra->GetNode( 8 )],
+    END_ELEM_WRITE( tetra );
+    
+  // pyramids
+  BEGIN_ELEM_WRITE( SMDSEntity_Pyramid, GmfPyramids, pyra )
+    node2IdMap[ pyra->GetNode( 0 )],
+    node2IdMap[ pyra->GetNode( 2 )],
+    node2IdMap[ pyra->GetNode( 1 )],
+    node2IdMap[ pyra->GetNode( 3 )],
+    node2IdMap[ pyra->GetNode( 4 )],
+    END_ELEM_WRITE( pyra );
+
+  // hexahedra
+  BEGIN_ELEM_WRITE( SMDSEntity_Hexa, GmfHexahedra, hexa )
+    node2IdMap[ hexa->GetNode( 0 )],
+    node2IdMap[ hexa->GetNode( 3 )],
+    node2IdMap[ hexa->GetNode( 2 )],
+    node2IdMap[ hexa->GetNode( 1 )],
+    node2IdMap[ hexa->GetNode( 4 )],
+    node2IdMap[ hexa->GetNode( 7 )],
+    node2IdMap[ hexa->GetNode( 6 )],
+    node2IdMap[ hexa->GetNode( 5 )],
+    END_ELEM_WRITE( hexa );
+
+  // tri-quadratic hexahedra
+  BEGIN_ELEM_WRITE( SMDSEntity_TriQuad_Hexa, GmfHexahedraQ2, hexa )
+    node2IdMap[ hexa->GetNode( 0 )],
+    node2IdMap[ hexa->GetNode( 3 )],
+    node2IdMap[ hexa->GetNode( 2 )],
+    node2IdMap[ hexa->GetNode( 1 )],
+    node2IdMap[ hexa->GetNode( 4 )],
+    node2IdMap[ hexa->GetNode( 7 )],
+    node2IdMap[ hexa->GetNode( 6 )],
+    node2IdMap[ hexa->GetNode( 5 )],
+    node2IdMap[ hexa->GetNode( 11 )],
+    node2IdMap[ hexa->GetNode( 10 )],
+    node2IdMap[ hexa->GetNode( 9 )],
+    node2IdMap[ hexa->GetNode( 8 )],
+    node2IdMap[ hexa->GetNode( 12 )],
+    node2IdMap[ hexa->GetNode( 15 )],
+    node2IdMap[ hexa->GetNode( 14 )],
+    node2IdMap[ hexa->GetNode( 13 )],
+    node2IdMap[ hexa->GetNode( 19 )],
+    node2IdMap[ hexa->GetNode( 18 )],
+    node2IdMap[ hexa->GetNode( 17 )],
+    node2IdMap[ hexa->GetNode( 16 )],
+    node2IdMap[ hexa->GetNode( 20 )],
+    node2IdMap[ hexa->GetNode( 24 )],
+    node2IdMap[ hexa->GetNode( 23 )],
+    node2IdMap[ hexa->GetNode( 22 )],
+    node2IdMap[ hexa->GetNode( 21 )],
+    node2IdMap[ hexa->GetNode( 25 )],
+    node2IdMap[ hexa->GetNode( 26 )],
+    END_ELEM_WRITE( hexa );
+
+  // prism
+  BEGIN_ELEM_WRITE( SMDSEntity_Penta, GmfPrisms, prism )
+    node2IdMap[ prism->GetNode( 0 )],
+    node2IdMap[ prism->GetNode( 2 )],
+    node2IdMap[ prism->GetNode( 1 )],
+    node2IdMap[ prism->GetNode( 3 )],
+    node2IdMap[ prism->GetNode( 5 )],
+    node2IdMap[ prism->GetNode( 4 )],
+    END_ELEM_WRITE( prism );
+
+
+  // required entities
+  SMESH_Comment badGroups;
+  const std::set<SMESHDS_GroupBase*>&      groupSet = myMesh->GetGroups();
+  std::set<SMESHDS_GroupBase*>::const_iterator grIt = groupSet.begin();
+  for ( ; grIt != groupSet.end(); ++grIt )
+  {
+    const SMESHDS_GroupBase* group = *grIt;
+    std::string          groupName = group->GetStoreName();
+    std::string::size_type     pos = groupName.find( "_required_" );
+    if ( pos == std::string::npos ) continue;
+
+    int                    gmfKwd;
+    SMDSAbs_EntityType smdsEntity;
+    std::string entity = groupName.substr( pos + strlen("_required_"));
+    if      ( entity == "Vertices" ) {
+      gmfKwd   = GmfRequiredVertices;
+      smdsEntity = SMDSEntity_Node;
+    }
+    else if ( entity == "Edges" ) {
+      gmfKwd   = GmfRequiredEdges;
+      smdsEntity = SMDSEntity_Edge;
+    }
+    else if ( entity == "Triangles" ) {
+      gmfKwd   = GmfRequiredTriangles;
+      smdsEntity = SMDSEntity_Triangle;
+    }
+    else if ( entity == "Quadrilaterals" ) {
+      gmfKwd   = GmfRequiredQuadrilaterals;
+      smdsEntity = SMDSEntity_Quadrangle;
+    }
+    else {
+      addMessage( SMESH_Comment("Invalig gmf entity name: ") << entity, /*fatal=*/false );
+      continue;
+    }
+
+    // check elem type in the group
+    int nbOkElems = 0;
+    SMDS_ElemIteratorPtr elemIt = group->GetElements();
+    while ( elemIt->more() )
+      nbOkElems += ( elemIt->next()->GetEntityType() == smdsEntity );
+
+    if ( nbOkElems != group->Extent() && nbOkElems == 0 )
+    {
+      badGroups << " " << groupName;
+      continue;
+    }
+
+    // choose a TElem2IDMap
+    TElem2IDMap* elem2IDMap = 0;
+    if ( smdsEntity == SMDSEntity_Quadrangle &&
+         myMesh->GetMeshInfo().NbEntities( smdsEntity ) != myMesh->NbFaces() )
+      elem2IDMap = & quad2IDMap;
+    else if ( smdsEntity == SMDSEntity_Triangle &&
+              myMesh->GetMeshInfo().NbEntities( smdsEntity ) != myMesh->NbFaces() )
+      elem2IDMap = & tria2IDMap;
+    else if ( smdsEntity == SMDSEntity_Edge &&
+              myMesh->GetMeshInfo().NbEntities( smdsEntity ) != myMesh->NbEdges() )
+      elem2IDMap = & edge2IDMap;
+
+    // write the group
+    GmfSetKwd( meshID, gmfKwd, nbOkElems );
+    if ( elem2IDMap )
+      for ( elemIt = group->GetElements(); elemIt->more(); )
+      {
+        const SMDS_MeshElement* elem = elemIt->next();
+        if ( elem->GetEntityType() == smdsEntity )
+          GmfSetLin( meshID, gmfKwd, (*elem2IDMap)[ elem ] );
+      }
+    else
+      for ( elemIt = group->GetElements(); elemIt->more(); )
+      {
+        const SMDS_MeshElement* elem = elemIt->next();
+        if ( elem->GetEntityType() == smdsEntity )
+          GmfSetLin( meshID, gmfKwd, elem->GetID() );
+      }
+
+  } // loop on groups
+
+  if ( !badGroups.empty() )
+    addMessage( SMESH_Comment("Groups including elements of inappropriate geometry:")
+                << badGroups, /*fatal=*/false );
+
+  return DRS_OK;
+}
diff --git a/src/DriverGMF/DriverGMF_Write.hxx b/src/DriverGMF/DriverGMF_Write.hxx
new file mode 100644 (file)
index 0000000..fd0918d
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File      : DriverGMF_Write.hxx
+// Created   : Mon Sep 17 15:36:47 2012
+// Author    : Edward AGAPOV (eap)
+
+
+#ifndef __DriverGMF_Write_HXX__
+#define __DriverGMF_Write_HXX__
+
+#include "SMESH_DriverGMF.hxx"
+
+#include "Driver_SMESHDS_Mesh.h"
+#include "SMDSAbs_ElementType.hxx"
+
+/*!
+ * \brief Driver Writing a mesh into a GMF file.
+ */
+class MESHDriverGMF_EXPORT DriverGMF_Write : public Driver_SMESHDS_Mesh
+{
+public:
+
+  DriverGMF_Write();
+  ~DriverGMF_Write();
+
+  virtual Status Perform();
+};
+
+/*!
+ * \brief An object closing GMF mesh at destruction
+ */
+struct DriverGMF_MeshCloser
+{
+  int _gmfMeshID;
+  DriverGMF_MeshCloser( const int gmfMeshID ): _gmfMeshID(gmfMeshID) {}
+  ~DriverGMF_MeshCloser();
+};
+
+
+#endif
diff --git a/src/DriverGMF/Makefile.am b/src/DriverGMF/Makefile.am
new file mode 100644 (file)
index 0000000..895c83a
--- /dev/null
@@ -0,0 +1,50 @@
+# Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# 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.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+include $(top_srcdir)/adm_local/unix/make_common_starter.am
+
+# header files 
+salomeinclude_HEADERS = \
+       DriverGMF_Read.hxx \
+       DriverGMF_Write.hxx \
+       SMESH_DriverGMF.hxx \
+       libmesh5.h
+
+# Libraries targets
+lib_LTLIBRARIES = libMeshDriverGMF.la
+dist_libMeshDriverGMF_la_SOURCES = \
+       DriverGMF_Read.cxx \
+       DriverGMF_Write.cxx \
+       libmesh5.c
+
+# additionnal information to compil and link file
+libMeshDriverGMF_la_CPPFLAGS = \
+       $(KERNEL_CXXFLAGS) \
+       $(CAS_CPPFLAGS) \
+        $(VTK_INCLUDES) \
+       $(BOOST_CPPFLAGS) \
+       -I$(srcdir)/../Driver \
+       -I$(srcdir)/../SMESHUtils \
+       -I$(srcdir)/../SMDS \
+       -I$(srcdir)/../SMESHDS
+
+libMeshDriverGMF_la_LDFLAGS  = \
+       $(BOOST_LIBS) \
+       ../Driver/libMeshDriver.la \
+       ../SMESHUtils/libSMESHUtils.la
diff --git a/src/DriverGMF/SMESH_DriverGMF.hxx b/src/DriverGMF/SMESH_DriverGMF.hxx
new file mode 100755 (executable)
index 0000000..dd901a3
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  File   : SMESH_DriverGMF.hxx
+//  Author : Alexander A. BORODIN
+//  Module : SMESH
+//
+#ifndef _SMESH_DriverGMF_HXX_
+#define _SMESH_DriverGMF_HXX_
+
+#ifdef WNT
+ #if defined MESHDriverGMF_EXPORTS || defined MeshDriverGMF_EXPORTS
+  #define MESHDriverGMF_EXPORT __declspec( dllexport )
+ #else
+  #define MESHDriverGMF_EXPORT __declspec( dllimport )
+ #endif
+#else
+ #define MESHDriverGMF_EXPORT
+#endif
+
+#endif
diff --git a/src/DriverGMF/libmesh5.c b/src/DriverGMF/libmesh5.c
new file mode 100644 (file)
index 0000000..b16c39c
--- /dev/null
@@ -0,0 +1,1346 @@
+
+
+/*----------------------------------------------------------*/
+/*                                                                                                                     */
+/*                                             LIBMESH V 5.46                                          */
+/*                                                                                                                     */
+/*----------------------------------------------------------*/
+/*                                                                                                                     */
+/*     Description:            handle .meshb file format I/O           */
+/*     Author:                         Loic MARECHAL                                           */
+/*     Creation date:          feb 16 2007                                                     */
+/*     Last modification:      apr 03 2012                                                     */
+/*                                                                                                                     */
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Includes                                                                                                    */
+/*----------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <ctype.h>
+#include "libmesh5.h"
+
+
+/*----------------------------------------------------------*/
+/* Defines                                                                                                     */
+/*----------------------------------------------------------*/
+
+#define Asc 1
+#define Bin 2
+#define MshFil 4
+#define SolFil 8
+#define MaxMsh 100
+#define InfKwd 1
+#define RegKwd 2
+#define SolKwd 3
+#define WrdSiz 4
+#define BufSiz 10000
+
+
+/*----------------------------------------------------------*/
+/* Structures                                                                                          */
+/*----------------------------------------------------------*/
+
+typedef struct
+{
+       int typ, SolSiz, NmbWrd, NmbLin, NmbTyp, TypTab[ GmfMaxTyp ];
+       long pos;
+       char fmt[ GmfMaxTyp*9 ];
+}KwdSct;
+
+typedef struct
+{
+       int dim, ver, mod, typ, cod, pos;
+       long NexKwdPos, siz;
+       KwdSct KwdTab[ GmfMaxKwd + 1 ];
+       FILE *hdl;
+       int *IntBuf;
+       float *FltBuf;
+       unsigned char *buf;
+       char FilNam[ GmfStrSiz ];
+       double DblBuf[1000/8];
+       unsigned char blk[ BufSiz + 1000 ];
+}GmfMshSct;
+
+
+/*----------------------------------------------------------*/
+/* Global variables                                                                                    */
+/*----------------------------------------------------------*/
+
+static int GmfIniFlg=0;
+static GmfMshSct *GmfMshTab[ MaxMsh + 1 ];
+static const char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] = 
+{      {"Reserved", "", "", ""},
+       {"MeshVersionFormatted", "", "", "i"},
+       {"Reserved", "", "", ""},
+       {"Dimension", "", "", "i"},
+       {"Vertices", "Vertex", "i", "dri"},
+       {"Edges", "Edge", "i", "iii"},
+       {"Triangles", "Triangle", "i", "iiii"},
+       {"Quadrilaterals", "Quadrilateral", "i", "iiiii"},
+       {"Tetrahedra", "Tetrahedron", "i", "iiiii"},
+       {"Prisms", "Prism", "i", "iiiiiii"},
+       {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"},
+       {"IterationsAll", "IterationAll","","i"},
+       {"TimesAll", "TimeAll","","r"},                                 
+       {"Corners", "Corner", "i", "i"},
+       {"Ridges", "Ridge", "i", "i"},
+       {"RequiredVertices", "RequiredVertex", "i", "i"},
+       {"RequiredEdges", "RequiredEdge", "i", "i"},
+       {"RequiredTriangles", "RequiredTriangle", "i", "i"},
+       {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"},
+       {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"},
+       {"NormalAtVertices", "NormalAtVertex", "i", "ii"},
+       {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"},
+       {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"},
+       {"AngleOfCornerBound", "", "", "r"},
+       {"TrianglesP2", "TriangleP2", "i", "iiiiiii"},
+       {"EdgesP2", "EdgeP2", "i", "iiii"},
+       {"SolAtPyramids", "SolAtPyramid", "i", "sr"},
+       {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"},
+       {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"},
+       {"SubDomainFromGeom", "SubDomainFromGeom", "i", "iiii"},
+       {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"},
+       {"Fault_NearTri", "Fault_NearTri", "i", "i"},
+       {"Fault_Inter", "Fault_Inter", "i", "i"},
+       {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"},
+       {"ExtraVerticesAtEdges", "ExtraVerticesAtEdge", "i", "in"},
+       {"ExtraVerticesAtTriangles", "ExtraVerticesAtTriangle", "i", "in"},
+       {"ExtraVerticesAtQuadrilaterals", "ExtraVerticesAtQuadrilateral", "i", "in"},
+       {"ExtraVerticesAtTetrahedra", "ExtraVerticesAtTetrahedron", "i", "in"},
+       {"ExtraVerticesAtPrisms", "ExtraVerticesAtPrism", "i", "in"},
+       {"ExtraVerticesAtHexahedra", "ExtraVerticesAtHexahedron", "i", "in"},
+       {"VerticesOnGeometricVertices", "VertexOnGeometricVertex", "i", "iir"},
+       {"VerticesOnGeometricEdges", "VertexOnGeometricEdge", "i", "iirr"},
+       {"VerticesOnGeometricTriangles", "VertexOnGeometricTriangle", "i", "iirrr"},
+       {"VerticesOnGeometricQuadrilaterals", "VertexOnGeometricQuadrilateral", "i", "iirrr"},
+       {"EdgesOnGeometricEdges", "EdgeOnGeometricEdge", "i", "iir"},
+       {"Fault_FreeEdge", "Fault_FreeEdge", "i", "i"},
+       {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"},
+       {"Polygons", "Polygon", "", "iiiiiiiii"},
+       {"Fault_Overlap", "Fault_Overlap", "i", "i"},
+       {"Pyramids", "Pyramid", "i", "iiiiii"},
+       {"BoundingBox", "", "", "drdr"},
+       {"Body","i", "drdrdrdr"},
+       {"PrivateTable", "PrivateTable", "i", "i"},
+       {"Fault_BadShape", "Fault_BadShape", "i", "i"},
+       {"End", "", "", ""},
+       {"TrianglesOnGeometricTriangles", "TriangleOnGeometricTriangle", "i", "iir"},
+       {"TrianglesOnGeometricQuadrilaterals", "TriangleOnGeometricQuadrilateral", "i", "iir"},
+       {"QuadrilateralsOnGeometricTriangles", "QuadrilateralOnGeometricTriangle", "i", "iir"},
+       {"QuadrilateralsOnGeometricQuadrilaterals", "QuadrilateralOnGeometricQuadrilateral", "i", "iir"},
+       {"Tangents", "Tangent", "i", "dr"},
+       {"Normals", "Normal", "i", "dr"},
+       {"TangentAtVertices", "TangentAtVertex", "i", "ii"},
+       {"SolAtVertices", "SolAtVertex", "i", "sr"},
+       {"SolAtEdges", "SolAtEdge", "i", "sr"},
+       {"SolAtTriangles", "SolAtTriangle", "i", "sr"},
+       {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"},
+       {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"},
+       {"SolAtPrisms", "SolAtPrism", "i", "sr"},
+       {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"},
+       {"DSolAtVertices", "DSolAtVertex", "i", "sr"},
+       {"ISolAtVertices", "ISolAtVertex", "i", "i"},
+       {"ISolAtEdges", "ISolAtEdge", "i", "ii"},
+       {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"},
+       {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"},
+       {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"},
+       {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"},
+       {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"},
+       {"Iterations", "","","i"},
+       {"Time", "","","r"},
+       {"Fault_SmallTri", "Fault_SmallTri","i","i"},
+       {"CoarseHexahedra", "CoarseHexahedron", "i", "i"}
+ };
+
+
+/*----------------------------------------------------------*/
+/* Prototypes of local procedures                                                      */
+/*----------------------------------------------------------*/
+
+static void ScaWrd(GmfMshSct *, unsigned char *);
+static void ScaDblWrd(GmfMshSct *, unsigned char *);
+static void ScaBlk(GmfMshSct *, unsigned char *, int);
+static long GetPos(GmfMshSct *);
+static void RecWrd(GmfMshSct *, unsigned char *);
+static void RecDblWrd(GmfMshSct *, unsigned char *);
+static void RecBlk(GmfMshSct *, unsigned char *, int);
+static void SetPos(GmfMshSct *, long);
+static int ScaKwdTab(GmfMshSct *);
+static void ExpFmt(GmfMshSct *, int);
+static void ScaKwdHdr(GmfMshSct *, int);
+
+
+/*----------------------------------------------------------*/
+/* Open a mesh file in read or write mod                                       */
+/*----------------------------------------------------------*/
+
+int GmfOpenMesh(const char *FilNam, int mod, ...)
+{
+       int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0;
+       char str[ GmfStrSiz ];
+       va_list VarArg;
+       GmfMshSct *msh;
+       char *ptr;
+       int k;
+
+       if(!GmfIniFlg)
+       {
+               for(i=0;i<=MaxMsh;i++)
+                       GmfMshTab[i] = NULL;
+
+               GmfIniFlg = 1;
+       }
+
+       /*---------------------*/
+       /* MESH STRUCTURE INIT */
+       /*---------------------*/
+
+       for(i=1;i<=MaxMsh;i++)
+               if(!GmfMshTab[i])
+               {
+                       MshIdx = i;
+                       break;
+               }
+
+       if( !MshIdx || !(msh = calloc(1, sizeof(GmfMshSct))) )
+               return(0);
+
+       /* Copy the FilNam into the structure */
+
+       if(strlen(FilNam) + 7 >= GmfStrSiz)
+        {
+                free (msh);
+               return(0);
+        }
+
+       strcpy(msh->FilNam, FilNam);
+
+       /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */
+
+       msh->mod = mod;
+       msh->buf = (unsigned char *)msh->DblBuf;
+       msh->FltBuf = (float *)msh->DblBuf;
+       msh->IntBuf = (int *)msh->DblBuf;
+
+       k = strlen(msh->FilNam) - 6;
+       if(k < 0)
+               k = 0;
+       ptr = msh->FilNam+k;
+       if(strstr(ptr, ".meshb"))
+               msh->typ |= (Bin | MshFil);
+       else if(strstr(ptr, ".mesh"))
+               msh->typ |= (Asc | MshFil);
+       else if(strstr(ptr, ".solb"))
+               msh->typ |= (Bin | SolFil);
+       else if(strstr(ptr, ".sol"))
+               msh->typ |= (Asc | SolFil);
+       else {
+               free (msh);
+               return(0);
+       }
+
+       /* Open the file in the required mod and initialyse the mesh structure */
+
+       if(msh->mod == GmfRead)
+       {
+
+               /*-----------------------*/
+               /* OPEN FILE FOR READING */
+               /*-----------------------*/
+
+               va_start(VarArg, mod);
+               PtrVer = va_arg(VarArg, int *);
+               PtrDim = va_arg(VarArg, int *);
+               va_end(VarArg);
+
+               /* Create the name string and open the file */
+
+               if(!(msh->hdl = fopen(msh->FilNam, "rb")))
+               {
+                       free (msh);
+                       return(0);
+               }
+
+               /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
+
+               if(msh->typ & Bin)
+               {
+                       fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl);
+
+                       if( (msh->cod != 1) && (msh->cod != 16777216) )
+                       {
+                               free (msh);
+                               return(0);
+                       }
+
+                       ScaWrd(msh, (unsigned char *)&msh->ver);
+
+                       if( (msh->ver < 1) || (msh->ver > 3) )
+                       {
+                               free (msh);
+                               return(0);
+                       }
+
+                       if( (msh->ver == 3) && (sizeof(long) == 4) )
+                       {
+                               free (msh);
+                               return(0);
+                       }
+
+                       ScaWrd(msh, (unsigned char *)&KwdCod);
+
+                       if(KwdCod != GmfDimension)
+                       {
+                               free (msh);
+                               return(0);
+                       }
+
+                       GetPos(msh);
+                       ScaWrd(msh, (unsigned char *)&msh->dim);
+               }
+               else
+               {
+                       do
+                       {
+                               res = fscanf(msh->hdl, "%s", str);
+                       }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") );
+
+                       if(res == EOF)
+                       {
+                               free (msh);
+                               return(0);
+                       }
+
+                       fscanf(msh->hdl, "%d", &msh->ver);
+
+                       if( (msh->ver < 1) || (msh->ver > 3) )
+                       {
+                               free (msh);
+                               return(0);
+                       }
+
+                       do
+                       {
+                               res = fscanf(msh->hdl, "%s", str);
+                       }while( (res != EOF) && strcmp(str, "Dimension") );
+
+                       if(res == EOF)
+                       {
+                               free (msh);
+                               return(0);
+                       }
+
+                       fscanf(msh->hdl, "%d", &msh->dim);
+               }
+
+               if( (msh->dim != 2) && (msh->dim != 3) )
+               {
+                       free (msh);
+                       return(0);
+               }
+
+               (*PtrVer) = msh->ver;
+               (*PtrDim) = msh->dim;
+
+               /*------------*/
+               /* KW READING */
+               /*------------*/
+
+               /* Read the list of kw present in the file */
+
+               if(!ScaKwdTab(msh))
+               {
+                       free (msh);
+                       return(0);
+               }
+
+               GmfMshTab[ MshIdx ] = msh;
+
+               return(MshIdx);
+       }
+       else if(msh->mod == GmfWrite)
+       {
+
+               /*-----------------------*/
+               /* OPEN FILE FOR WRITING */
+               /*-----------------------*/
+
+               msh->cod = 1;
+
+               /* Check if the user provided a valid version number and dimension */
+
+               va_start(VarArg, mod);
+               msh->ver = va_arg(VarArg, int);
+               msh->dim = va_arg(VarArg, int);
+               va_end(VarArg);
+
+               if( (msh->ver < 1) || (msh->ver > 3) )
+               {
+                       free (msh);
+                       return(0);
+               }
+
+               if( (msh->ver == 3) && (sizeof(long) == 4) )
+               {
+                       free (msh);
+                       return(0);
+               }
+
+               if( (msh->dim != 2) && (msh->dim != 3) )
+               {
+                       free (msh);
+                       return(0);
+               }
+
+               /* Create the mesh file */
+
+               if(!(msh->hdl = fopen(msh->FilNam, "wb")))
+               {
+                       free (msh);
+                       return(0);
+               }
+
+               GmfMshTab[ MshIdx ] = msh;
+
+
+               /*------------*/
+               /* KW WRITING */
+               /*------------*/
+
+               /* Write the mesh version and dimension */
+
+               if(msh->typ & Asc)
+               {
+                       fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver);
+                       fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim);
+               }
+               else
+               {
+                       RecWrd(msh, (unsigned char *)&msh->cod);
+                       RecWrd(msh, (unsigned char *)&msh->ver);
+                       GmfSetKwd(MshIdx, GmfDimension, 0);
+                       RecWrd(msh, (unsigned char *)&msh->dim);
+               }
+
+               return(MshIdx);
+       }
+       else
+       {
+                free (msh);
+               return(0);
+        }
+}
+
+
+/*----------------------------------------------------------*/
+/* Close a meshfile in the right way                                           */
+/*----------------------------------------------------------*/
+
+int GmfCloseMesh(int MshIdx)
+{
+       int res = 1;
+       GmfMshSct *msh;
+
+       if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+               return(0);
+
+       msh = GmfMshTab[ MshIdx ];
+       RecBlk(msh, msh->buf, 0);
+
+       /* In write down the "End" kw in write mode */
+
+       if(msh->mod == GmfWrite){
+               if(msh->typ & Asc)
+                       fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]);
+               else
+                       GmfSetKwd(MshIdx, GmfEnd, 0);
+       }
+       /* Close the file and free the mesh structure */
+
+       if(fclose(msh->hdl))
+               res = 0;
+
+       free(msh);
+       GmfMshTab[ MshIdx ] = NULL;
+
+       return(res);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read the number of lines and set the position to this kwd*/
+/*----------------------------------------------------------*/
+
+int GmfStatKwd(int MshIdx, int KwdCod, ...)
+{
+       int i, *PtrNmbTyp, *PtrSolSiz, *TypTab;
+       GmfMshSct *msh;
+       KwdSct *kwd;
+       va_list VarArg;
+
+       if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+               return(0);
+
+       msh = GmfMshTab[ MshIdx ];
+
+       if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+               return(0);
+
+       kwd = &msh->KwdTab[ KwdCod ];
+
+       if(!kwd->NmbLin)
+               return(0);
+
+       /* Read further arguments if this kw is a sol */
+
+       if(kwd->typ == SolKwd)
+       {
+               va_start(VarArg, KwdCod);
+
+               PtrNmbTyp = va_arg(VarArg, int *);
+               *PtrNmbTyp = kwd->NmbTyp;
+
+               PtrSolSiz = va_arg(VarArg, int *);
+               *PtrSolSiz = kwd->SolSiz;
+
+               TypTab = va_arg(VarArg, int *);
+
+               for(i=0;i<kwd->NmbTyp;i++)
+                       TypTab[i] = kwd->TypTab[i];
+
+               va_end(VarArg);
+       }
+
+       return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Set the current file position to a given kwd                                */
+/*----------------------------------------------------------*/
+
+int GmfGotoKwd(int MshIdx, int KwdCod)
+{
+       GmfMshSct *msh;
+       KwdSct *kwd;
+
+       if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+               return(0);
+
+       msh = GmfMshTab[ MshIdx ];
+
+       if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+               return(0);
+
+       kwd = &msh->KwdTab[ KwdCod ];
+
+       if(!kwd->NmbLin)
+               return(0);
+
+       return(fseek(msh->hdl, kwd->pos, SEEK_SET));
+}
+
+
+/*----------------------------------------------------------*/
+/* Write the kwd and set the number of lines                           */
+/*----------------------------------------------------------*/
+
+int GmfSetKwd(int MshIdx, int KwdCod, ...)
+{
+       int i, NmbLin=0, *TypTab;
+       long CurPos;
+       va_list VarArg;
+       GmfMshSct *msh;
+       KwdSct *kwd;
+
+       if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+               return(0);
+
+       msh = GmfMshTab[ MshIdx ];
+       RecBlk(msh, msh->buf, 0);
+
+       if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+               return(0);
+
+       kwd = &msh->KwdTab[ KwdCod ];
+
+       /* Read further arguments if this kw has a header */
+
+       if(strlen(GmfKwdFmt[ KwdCod ][2]))
+       {
+               va_start(VarArg, KwdCod);
+               NmbLin = va_arg(VarArg, int);
+
+               if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr"))
+               {
+                       kwd->NmbTyp = va_arg(VarArg, int);
+                       TypTab = va_arg(VarArg, int *);
+
+                       for(i=0;i<kwd->NmbTyp;i++)
+                               kwd->TypTab[i] = TypTab[i];
+               }
+
+               va_end(VarArg);
+       }
+
+       /* Setup the kwd info */
+
+       ExpFmt(msh, KwdCod);
+
+       if(!kwd->typ)
+               return(0);
+       else if(kwd->typ == InfKwd)
+               kwd->NmbLin = 1;
+       else
+               kwd->NmbLin = NmbLin;
+
+       /* Store the next kwd position in binary file */
+
+       if( (msh->typ & Bin) && msh->NexKwdPos )
+       {
+               CurPos = ftell(msh->hdl);
+               fseek(msh->hdl, msh->NexKwdPos, SEEK_SET);
+               SetPos(msh, CurPos);
+               fseek(msh->hdl, CurPos, SEEK_SET);
+       }
+
+       /* Write the header */
+
+       if(msh->typ & Asc)
+       {
+               fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]);
+
+               if(kwd->typ != InfKwd)
+                       fprintf(msh->hdl, "%d\n", kwd->NmbLin);
+
+               /* In case of solution field, write the extended header */
+
+               if(kwd->typ == SolKwd)
+               {
+                       fprintf(msh->hdl, "%d ", kwd->NmbTyp);
+
+                       for(i=0;i<kwd->NmbTyp;i++)
+                               fprintf(msh->hdl, "%d ", kwd->TypTab[i]);
+
+                       fprintf(msh->hdl, "\n\n");
+               }
+       }
+       else
+       {
+               RecWrd(msh, (unsigned char *)&KwdCod);
+               msh->NexKwdPos = ftell(msh->hdl);
+               SetPos(msh, 0);
+
+               if(kwd->typ != InfKwd)
+                       RecWrd(msh, (unsigned char *)&kwd->NmbLin);
+
+               /* In case of solution field, write the extended header at once */
+
+               if(kwd->typ == SolKwd)
+               {
+                       RecWrd(msh, (unsigned char *)&kwd->NmbTyp);
+
+                       for(i=0;i<kwd->NmbTyp;i++)
+                               RecWrd(msh, (unsigned char *)&kwd->TypTab[i]);
+               }
+       }
+
+       /* Reset write buffer position */
+       msh->pos = 0;
+
+       /* Estimate the total file size and check whether it crosses the 2GB threshold */
+
+       msh->siz += kwd->NmbLin * kwd->NmbWrd * WrdSiz;
+
+       if(msh->siz > 2E9)
+               return(0);
+       else
+               return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a full line from the current kwd                                       */
+/*----------------------------------------------------------*/
+
+void GmfGetLin(int MshIdx, int KwdCod, ...)
+{
+       int i, j;
+       float *FltSolTab;
+       double *DblSolTab;
+       va_list VarArg;
+       GmfMshSct *msh = GmfMshTab[ MshIdx ];
+       KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+       /* Start decoding the arguments */
+
+       va_start(VarArg, KwdCod);
+
+       if(kwd->typ != SolKwd)
+       {
+               int k, nb_repeat = 0;
+
+               if(msh->ver == 1)
+               {
+                       if(msh->typ & Asc)
+                       {
+                               for(i=0;i<kwd->SolSiz;i++)
+                                       if(kwd->fmt[i] == 'r')
+                                               fscanf(msh->hdl, "%f", va_arg(VarArg, float *));
+                                       else if(kwd->fmt[i] == 'n') {
+                                               fscanf(msh->hdl, "%d", &nb_repeat);
+                                               *(va_arg(VarArg,  int *)) = nb_repeat;
+                                               for(k=0;k<nb_repeat;k++)
+                                                       fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
+                                       }
+                                       else
+                                               fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
+                       }
+                       else
+                       {
+                               for(i=0;i<kwd->SolSiz;i++)
+                                       if(kwd->fmt[i] == 'r')
+                                               ScaWrd(msh, (unsigned char *)va_arg(VarArg, float *));
+                                       else if(kwd->fmt[i] == 'n') {
+                                               ScaWrd(msh, (unsigned char *)&nb_repeat);
+                                               *(va_arg(VarArg,  int *)) = nb_repeat;
+                                               for(k=0;k<nb_repeat;k++)
+                                                       ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
+                                       }
+                                       else
+                                               ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
+                       }
+               }
+               else
+               {
+                       if(msh->typ & Asc)
+                       {
+                               for(i=0;i<kwd->SolSiz;i++)
+                                       if(kwd->fmt[i] == 'r')
+                                               fscanf(msh->hdl, "%lf", va_arg(VarArg, double *));
+                                       else if(kwd->fmt[i] == 'n') {
+                                               fscanf(msh->hdl, "%d", &nb_repeat);
+                                               *(va_arg(VarArg,  int *)) = nb_repeat;
+                                               for(k=0;k<nb_repeat;k++)
+                                                       fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
+                                       }
+                                       else
+                                               fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
+                       }
+                       else
+                               for(i=0;i<kwd->SolSiz;i++)
+                                       if(kwd->fmt[i] == 'r')
+                                               ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *));
+                                       else if(kwd->fmt[i] == 'n') {
+                                               ScaWrd(msh, (unsigned char *)&nb_repeat);
+                                               *(va_arg(VarArg,  int *)) = nb_repeat;
+                                               for(k=0;k<nb_repeat;k++)
+                                                       ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
+                                       }
+                                       else
+                                               ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
+               }
+       }
+       else
+       {
+               if(msh->ver == 1)
+               {
+                       FltSolTab = va_arg(VarArg, float *);
+
+                       if(msh->typ & Asc)
+                               for(j=0;j<kwd->SolSiz;j++)
+                                       fscanf(msh->hdl, "%f", &FltSolTab[j]);
+                       else
+                               ScaBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
+               }
+               else
+               {
+                       DblSolTab = va_arg(VarArg, double *);
+
+                       if(msh->typ & Asc)
+                               for(j=0;j<kwd->SolSiz;j++)
+                                       fscanf(msh->hdl, "%lf", &DblSolTab[j]);
+                       else
+                               for(j=0;j<kwd->SolSiz;j++)
+                                       ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]);
+               }
+       }
+
+       va_end(VarArg);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a full line from the current kwd                                      */
+/*----------------------------------------------------------*/
+
+void GmfSetLin(int MshIdx, int KwdCod, ...)
+{
+       int i, j, pos, *IntBuf;
+       float *FltSolTab;
+       double *DblSolTab, *DblBuf;
+       va_list VarArg;
+       GmfMshSct *msh = GmfMshTab[ MshIdx ];
+       KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+       /* Start decoding the arguments */
+
+       va_start(VarArg, KwdCod);
+
+       if(kwd->typ != SolKwd)
+       {
+               int k, nb_repeat = 0;
+
+               if(msh->ver == 1)
+               {
+                       if(msh->typ & Asc)
+                       {
+                               for(i=0;i<kwd->SolSiz;i++)
+                                       if(kwd->fmt[i] == 'r')
+                                               fprintf(msh->hdl, "%g ", (float)va_arg(VarArg, double));
+                                       else if(kwd->fmt[i] == 'n') {
+                                               nb_repeat = va_arg(VarArg, int);
+                                               fprintf(msh->hdl, "%d ", nb_repeat);
+                                               for(k=0;k<nb_repeat;k++)
+                                                       fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
+                                       }
+                                       else
+                                               fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
+                       }
+                       else
+                       {
+                               int size_of_block = kwd->SolSiz;
+                               for(i=0;i<kwd->SolSiz;i++)
+                                       if(kwd->fmt[i] == 'r')
+                                               msh->FltBuf[i] = va_arg(VarArg, double);
+                                       else if(kwd->fmt[i] == 'n') {
+                                               nb_repeat = va_arg(VarArg, int);
+                                               msh->FltBuf[i] = nb_repeat;
+                                               for(k=0;k<nb_repeat;k++) {
+                                                       msh->IntBuf[i+1+k] = va_arg(VarArg, int);
+                                                       size_of_block ++;
+                                               }
+                                       }
+                                       else
+                                               msh->IntBuf[i] = va_arg(VarArg, int);
+
+                               RecBlk(msh, msh->buf, size_of_block);
+                       }
+               }
+               else
+               {
+                       if(msh->typ & Asc)
+                       {
+                               for(i=0;i<kwd->SolSiz;i++)
+                                       if(kwd->fmt[i] == 'r')
+                                               fprintf(msh->hdl, "%.15lg ", va_arg(VarArg, double));
+                                       else if(kwd->fmt[i] == 'n') {
+                                               nb_repeat = va_arg(VarArg, int);
+                                               fprintf(msh->hdl, "%d ", nb_repeat);
+                                               for(k=0;k<nb_repeat;k++)
+                                                       fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
+                                       }
+                                       else
+                                               fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
+                       }
+                       else
+                       {
+                               pos = 0;
+
+                               for(i=0;i<kwd->SolSiz;i++)
+                                       if(kwd->fmt[i] == 'r')
+                                       {
+                                               DblBuf = (double *)&msh->buf[ pos ];
+                                               *DblBuf = va_arg(VarArg, double);
+                                               pos += 8;
+                                       }
+                                       else if(kwd->fmt[i] == 'n')
+                                       {
+                                               IntBuf = (int *)&msh->buf[ pos ];
+                                               nb_repeat = va_arg(VarArg, int);
+                                               *IntBuf = nb_repeat;
+                                               pos += 4;
+                                               for(k=0;k<nb_repeat;k++) {
+                                                       IntBuf = (int *)&msh->buf[ pos ];
+                                                       *IntBuf = va_arg(VarArg, int);
+                                                       pos += 4;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               IntBuf = (int *)&msh->buf[ pos ];
+                                               *IntBuf = va_arg(VarArg, int);
+                                               pos += 4;
+                                       }
+                               RecBlk(msh, msh->buf, pos/4);
+                       }
+               }
+       }
+       else
+       {
+               if(msh->ver == 1)
+               {
+                       FltSolTab = va_arg(VarArg, float *);
+
+                       if(msh->typ & Asc)
+                               for(j=0;j<kwd->SolSiz;j++)
+                                       fprintf(msh->hdl, "%g ", FltSolTab[j]);
+                       else
+                               RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
+               }
+               else
+               {
+                       DblSolTab = va_arg(VarArg, double *);
+
+                       if(msh->typ & Asc)
+                               for(j=0;j<kwd->SolSiz;j++)
+                                       fprintf(msh->hdl, "%.15lg ", DblSolTab[j]);
+                       else
+                               RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd);
+               }
+       }
+
+       va_end(VarArg);
+
+       if(msh->typ & Asc)
+               fprintf(msh->hdl, "\n");
+}
+
+
+/*----------------------------------------------------------*/
+/* Private procedure for transmesh : copy a whole line         */
+/*----------------------------------------------------------*/
+
+void GmfCpyLin(int InpIdx, int OutIdx, int KwdCod)
+{
+       double d;
+       float f;
+       int i, a;
+       GmfMshSct *InpMsh = GmfMshTab[ InpIdx ], *OutMsh = GmfMshTab[ OutIdx ];
+       KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ];
+
+       for(i=0;i<kwd->SolSiz;i++)
+       {
+               if(kwd->fmt[i] == 'r')
+               {
+                       if(InpMsh->ver == 1)
+                       {
+                               if(InpMsh->typ & Asc)
+                                       fscanf(InpMsh->hdl, "%f", &f);
+                               else
+                                       ScaWrd(InpMsh, (unsigned char *)&f);
+
+                               d = f;
+                       }
+                       else
+                       {
+                               if(InpMsh->typ & Asc)
+                                       fscanf(InpMsh->hdl, "%lf", &d);
+                               else
+                                       ScaDblWrd(InpMsh, (unsigned char *)&d);
+
+                               f = (float)d;
+                       }
+
+                       if(OutMsh->ver == 1)
+                               if(OutMsh->typ & Asc)
+                                       fprintf(OutMsh->hdl, "%g ", f);
+                               else
+                                       RecWrd(OutMsh, (unsigned char *)&f);
+                       else
+                               if(OutMsh->typ & Asc)
+                                       fprintf(OutMsh->hdl, "%.15g ", d);
+                               else
+                                       RecDblWrd(OutMsh, (unsigned char *)&d);
+               }
+               else if(kwd->fmt[i] == 'n')
+               {
+                       int k, nb_repeat = 0;
+
+                       if(InpMsh->typ & Asc)
+                               fscanf(InpMsh->hdl, "%d", &a);
+                       else
+                               ScaWrd(InpMsh, (unsigned char *)&a);
+
+                       nb_repeat = a;
+
+                       if(OutMsh->typ & Asc)
+                               fprintf(OutMsh->hdl, "%d ", a);
+                       else
+                               RecWrd(OutMsh, (unsigned char *)&a);
+
+                       for(k=0;k<nb_repeat;k++) {
+                               if(InpMsh->typ & Asc)
+                                       fscanf(InpMsh->hdl, "%d", &a);
+                               else
+                                       ScaWrd(InpMsh, (unsigned char *)&a);
+
+                               if(OutMsh->typ & Asc)
+                                       fprintf(OutMsh->hdl, "%d ", a);
+                               else
+                                       RecWrd(OutMsh, (unsigned char *)&a);
+                       }
+               }
+               else
+               {
+                       if(InpMsh->typ & Asc)
+                               fscanf(InpMsh->hdl, "%d", &a);
+                       else
+                               ScaWrd(InpMsh, (unsigned char *)&a);
+
+                       if(OutMsh->typ & Asc)
+                               fprintf(OutMsh->hdl, "%d ", a);
+                       else
+                               RecWrd(OutMsh, (unsigned char *)&a);
+               }
+       }
+
+       if(OutMsh->typ & Asc)
+               fprintf(OutMsh->hdl, "\n");
+}
+
+
+/*----------------------------------------------------------*/
+/* Find every kw present in a meshfile                                         */
+/*----------------------------------------------------------*/
+
+static int ScaKwdTab(GmfMshSct *msh)
+{
+       int KwdCod;
+       long  NexPos, CurPos, EndPos;
+       char str[ GmfStrSiz ];
+
+       if(msh->typ & Asc)
+       {
+               /* Scan each string in the file until the end */
+
+               while(fscanf(msh->hdl, "%s", str) != EOF)
+               {
+                       /* Fast test in order to reject quickly the numeric values */
+
+                       if(isalpha(str[0]))
+                       {
+                               /* Search which kwd code this string is associated with, 
+                                       then get its header and save the curent position in file (just before the data) */
+
+                               for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++)
+                                       if(!strcmp(str, GmfKwdFmt[ KwdCod ][0]))
+                                       {
+                                               ScaKwdHdr(msh, KwdCod);
+                                               break;
+                                       }
+                       }
+                       else if(str[0] == '#')
+                               while(fgetc(msh->hdl) != '\n');
+               }
+       }
+       else
+       {
+               /* Get file size */
+
+               CurPos = ftell(msh->hdl);
+               fseek(msh->hdl, 0, SEEK_END);
+               EndPos = ftell(msh->hdl);
+               fseek(msh->hdl, CurPos, SEEK_SET);
+
+               /* Jump through kwd positions in the file */
+
+               do
+               {
+                       /* Get the kwd code and the next kwd position */
+
+                       ScaWrd(msh, (unsigned char *)&KwdCod);
+                       NexPos = GetPos(msh);
+
+                       if(NexPos > EndPos)
+                               return(0);
+
+                       /* Check if this kwd belongs to this mesh version */
+
+                       if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) )
+                               ScaKwdHdr(msh, KwdCod);
+
+                       /* Go to the next kwd */
+
+                       if(NexPos)
+                               fseek(msh->hdl, NexPos, SEEK_SET);
+               }while(NexPos && (KwdCod != GmfEnd));
+       }
+
+       return(1);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read and setup the keyword's header                                         */
+/*----------------------------------------------------------*/
+
+static void ScaKwdHdr(GmfMshSct *msh, int KwdCod)
+{
+       int i;
+       KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+       if(!strcmp("i", GmfKwdFmt[ KwdCod ][2]))
+       {
+               if(msh->typ & Asc)
+                       fscanf(msh->hdl, "%d", &kwd->NmbLin);
+               else
+                       ScaWrd(msh, (unsigned char *)&kwd->NmbLin);
+       }
+       else
+               kwd->NmbLin = 1;
+
+       if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3]))
+       {
+               if(msh->typ & Asc)
+               {
+                       fscanf(msh->hdl, "%d", &kwd->NmbTyp);
+
+                       for(i=0;i<kwd->NmbTyp;i++)
+                               fscanf(msh->hdl, "%d", &kwd->TypTab[i]);
+               }
+               else
+               {
+                       ScaWrd(msh, (unsigned char *)&kwd->NmbTyp);
+
+                       for(i=0;i<kwd->NmbTyp;i++)
+                               ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]);
+               }
+       }
+
+       ExpFmt(msh, KwdCod);
+       kwd->pos = ftell(msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Expand the compacted format and compute the line size       */
+/*----------------------------------------------------------*/
+
+static void ExpFmt(GmfMshSct *msh, int KwdCod)
+{
+       int i, j, TmpSiz=0;
+       char chr;
+       const char *InpFmt = GmfKwdFmt[ KwdCod ][3];
+       KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+       /* Set the kwd's type */
+
+       if(!strlen(GmfKwdFmt[ KwdCod ][2]))
+               kwd->typ = InfKwd;
+       else if(!strcmp(InpFmt, "sr"))
+               kwd->typ = SolKwd;
+       else
+               kwd->typ = RegKwd;
+
+       /* Get the solution-field's size */
+
+       if(kwd->typ == SolKwd)
+               for(i=0;i<kwd->NmbTyp;i++)
+                       switch(kwd->TypTab[i])
+                       {
+                               case GmfSca    : TmpSiz += 1; break;
+                               case GmfVec    : TmpSiz += msh->dim; break;
+                               case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break;
+                               case GmfMat    : TmpSiz += msh->dim * msh->dim; break;
+                       }
+
+       /* Scan each character from the format string */
+
+       i = kwd->SolSiz = kwd->NmbWrd = 0;
+
+       while(i < strlen(InpFmt))
+       {
+               chr = InpFmt[ i++ ];
+
+               if(chr == 'd')
+               {
+                       chr = InpFmt[i++];
+
+                       for(j=0;j<msh->dim;j++)
+                               kwd->fmt[ kwd->SolSiz++ ] = chr;
+               }
+               else if(chr == 's')
+               {
+                       chr = InpFmt[i++];
+
+                       for(j=0;j<TmpSiz;j++)
+                               kwd->fmt[ kwd->SolSiz++ ] = chr;
+               }
+               else
+                       kwd->fmt[ kwd->SolSiz++ ] = chr;
+       }
+
+       for(i=0;i<kwd->SolSiz;i++)
+               if(kwd->fmt[i] == 'i')
+                       kwd->NmbWrd++;
+               else if(msh->ver >= 2)
+                       kwd->NmbWrd += 2;
+               else
+                       kwd->NmbWrd++;
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a four bytes word from a mesh file                                     */
+/*----------------------------------------------------------*/
+
+static void ScaWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+       unsigned char swp;
+
+       fread(wrd, WrdSiz, 1, msh->hdl);
+
+       if(msh->cod == 1)
+               return;
+
+       swp = wrd[3];
+       wrd[3] = wrd[0];
+       wrd[0] = swp;
+
+       swp = wrd[2];
+       wrd[2] = wrd[1];
+       wrd[1] = swp;
+}
+
+
+/*----------------------------------------------------------*/
+/* Read an eight bytes word from a mesh file                           */
+/*----------------------------------------------------------*/
+
+static void ScaDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+       int i;
+       unsigned char swp;
+
+       fread(wrd, WrdSiz, 2, msh->hdl);
+
+       if(msh->cod == 1)
+               return;
+
+       for(i=0;i<4;i++)
+       {
+               swp = wrd[7-i];
+               wrd[7-i] = wrd[i];
+               wrd[i] = swp;
+       }
+}
+
+
+/*----------------------------------------------------------*/
+/* Read ablock of four bytes word from a mesh file                     */
+/*----------------------------------------------------------*/
+
+static void ScaBlk(GmfMshSct *msh, unsigned char *blk, int siz)
+{
+       int i, j;
+       unsigned char swp, *wrd;
+
+       fread(blk, WrdSiz, siz, msh->hdl);
+
+       if(msh->cod == 1)
+               return;
+
+       for(i=0;i<siz;i++)
+       {
+               wrd = &blk[ i * 4 ];
+
+               for(j=0;j<2;j++)
+               {
+                       swp = wrd[ 3-j ];
+                       wrd[ 3-j ] = wrd[j];
+                       wrd[j] = swp;
+               }
+       }
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a 4 or 8 bytes position in mesh file                           */
+/*----------------------------------------------------------*/
+
+static long GetPos(GmfMshSct *msh)
+{
+       int IntVal;
+       long pos;
+
+       if(msh->ver >= 3)
+               ScaDblWrd(msh, (unsigned char*)&pos);
+       else
+       {
+               ScaWrd(msh, (unsigned char*)&IntVal);
+               pos = IntVal;
+       }
+
+       return(pos);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a four bytes word to a mesh file                                      */
+/*----------------------------------------------------------*/
+
+static void RecWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+       fwrite(wrd, WrdSiz, 1, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write an eight bytes word to a mesh file                                    */
+/*----------------------------------------------------------*/
+
+static void RecDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+       fwrite(wrd, WrdSiz, 2, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a block of four bytes word to a mesh file                     */
+/*----------------------------------------------------------*/
+
+static void RecBlk(GmfMshSct *msh, unsigned char *blk, int siz)
+{
+       /* Copy this line-block into the main mesh buffer */
+
+       if(siz)
+       {
+               memcpy(&msh->blk[ msh->pos ], blk, siz * WrdSiz);
+               msh->pos += siz * WrdSiz;
+       }
+
+       /* When the buffer is full or this procedure is called with a 0 size, flush the cache on disk */
+
+       if( (msh->pos > BufSiz) || (!siz && msh->pos) )
+       {
+               fwrite(msh->blk, 1, msh->pos, msh->hdl);
+               msh->pos = 0;
+       }
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a 4 or 8 bytes position in a mesh file                                */
+/*----------------------------------------------------------*/
+
+static void SetPos(GmfMshSct *msh, long pos)
+{
+       int IntVal;
+
+       if(msh->ver >= 3)
+               RecDblWrd(msh, (unsigned char*)&pos);
+       else
+       {
+               IntVal = pos;
+               RecWrd(msh, (unsigned char*)&IntVal);
+       }
+}
diff --git a/src/DriverGMF/libmesh5.h b/src/DriverGMF/libmesh5.h
new file mode 100644 (file)
index 0000000..eddf200
--- /dev/null
@@ -0,0 +1,153 @@
+
+
+/*----------------------------------------------------------*/
+/*                                                                                                                     */
+/*                                             LIBMESH V 5.46                                          */
+/*                                                                                                                     */
+/*----------------------------------------------------------*/
+/*                                                                                                                     */
+/*     Description:            handle .meshb file format I/O           */
+/*     Author:                         Loic MARECHAL                                           */
+/*     Creation date:          feb 16 2007                                                     */
+/*     Last modification:      dec 09 2011                                                     */
+/*                                                                                                                     */
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Defines                                                                                                     */
+/*----------------------------------------------------------*/
+
+#define GmfStrSiz 1024
+#define GmfMaxTyp 1000
+#define GmfMaxKwd 80
+#define GmfMshVer 1
+#define GmfRead 1
+#define GmfWrite 2
+#define GmfSca 1
+#define GmfVec 2
+#define GmfSymMat 3
+#define GmfMat 4
+#define GmfFloat 1
+#define GmfDouble 2
+
+enum GmfKwdCod
+{
+       GmfReserved1, \
+       GmfVersionFormatted, \
+       GmfReserved2, \
+       GmfDimension, \
+       GmfVertices, \
+       GmfEdges, \
+       GmfTriangles, \
+       GmfQuadrilaterals, \
+       GmfTetrahedra, \
+       GmfPrisms, \
+       GmfHexahedra, \
+       GmfIterationsAll, \
+       GmfTimesAll, \
+       GmfCorners, \
+       GmfRidges, \
+       GmfRequiredVertices, \
+       GmfRequiredEdges, \
+       GmfRequiredTriangles, \
+       GmfRequiredQuadrilaterals, \
+       GmfTangentAtEdgeVertices, \
+       GmfNormalAtVertices, \
+       GmfNormalAtTriangleVertices, \
+       GmfNormalAtQuadrilateralVertices, \
+       GmfAngleOfCornerBound, \
+       GmfTrianglesP2, \
+       GmfEdgesP2, \
+       GmfSolAtPyramids, \
+       GmfQuadrilateralsQ2, \
+       GmfISolAtPyramids, \
+       GmfSubDomainFromGeom, \
+       GmfTetrahedraP2, \
+       GmfFault_NearTri, \
+       GmfFault_Inter, \
+       GmfHexahedraQ2, \
+       GmfExtraVerticesAtEdges, \
+       GmfExtraVerticesAtTriangles, \
+       GmfExtraVerticesAtQuadrilaterals, \
+       GmfExtraVerticesAtTetrahedra, \
+       GmfExtraVerticesAtPrisms, \
+       GmfExtraVerticesAtHexahedra, \
+       GmfVerticesOnGeometricVertices, \
+       GmfVerticesOnGeometricEdges, \
+       GmfVerticesOnGeometricTriangles, \
+       GmfVerticesOnGeometricQuadrilaterals, \
+       GmfEdgesOnGeometricEdges, \
+       GmfFault_FreeEdge, \
+       GmfPolyhedra, \
+       GmfPolygons, \
+       GmfFault_Overlap, \
+       GmfPyramids, \
+       GmfBoundingBox, \
+       GmfBody, \
+       GmfPrivateTable, \
+       GmfFault_BadShape, \
+       GmfEnd, \
+       GmfTrianglesOnGeometricTriangles, \
+       GmfTrianglesOnGeometricQuadrilaterals, \
+       GmfQuadrilateralsOnGeometricTriangles, \
+       GmfQuadrilateralsOnGeometricQuadrilaterals, \
+       GmfTangents, \
+       GmfNormals, \
+       GmfTangentAtVertices, \
+       GmfSolAtVertices, \
+       GmfSolAtEdges, \
+       GmfSolAtTriangles, \
+       GmfSolAtQuadrilaterals, \
+       GmfSolAtTetrahedra, \
+       GmfSolAtPrisms, \
+       GmfSolAtHexahedra, \
+       GmfDSolAtVertices, \
+       GmfISolAtVertices, \
+       GmfISolAtEdges, \
+       GmfISolAtTriangles, \
+       GmfISolAtQuadrilaterals, \
+       GmfISolAtTetrahedra, \
+       GmfISolAtPrisms, \
+       GmfISolAtHexahedra, \
+       GmfIterations, \
+       GmfTime, \
+       GmfFault_SmallTri, \
+       GmfCoarseHexahedra
+};
+
+
+/*----------------------------------------------------------*/
+/* External procedures                                                                         */
+/*----------------------------------------------------------*/
+
+extern int GmfOpenMesh(const char *, int, ...);
+extern int GmfCloseMesh(int);
+extern int GmfStatKwd(int, int, ...);
+extern int GmfGotoKwd(int, int);
+extern int GmfSetKwd(int, int, ...);
+extern void GmfGetLin(int, int, ...);
+extern void GmfSetLin(int, int, ...);
+
+
+/*----------------------------------------------------------*/
+/* Fortran 77 API                                                                                      */
+/*----------------------------------------------------------*/
+
+#if defined(F77_NO_UNDER_SCORE)
+#define call(x) x
+#else
+#define call(x) x ## _
+#endif
+
+
+/*----------------------------------------------------------*/
+/* Transmesh private API                                                                       */
+/*----------------------------------------------------------*/
+
+#ifdef TRANSMESH
+
+extern char *GmfKwdFmt[ GmfMaxKwd + 1 ][4];
+extern int GmfCpyLin(int, int, int);
+
+#endif