Salome HOME
CS work : MeshGems reader/writer
authorAnthony Geay <anthony.geay@edf.fr>
Thu, 18 Feb 2021 09:28:12 +0000 (10:28 +0100)
committerAnthony Geay <anthony.geay@edf.fr>
Thu, 18 Feb 2021 09:28:12 +0000 (10:28 +0100)
src/MEDLoader/CMakeLists.txt
src/MEDLoader/MEDMESHConverterUtilities.cxx [new file with mode: 0644]
src/MEDLoader/MEDMESHConverterUtilities.hxx [new file with mode: 0644]
src/MEDLoader/MeshFormatReader.cxx [new file with mode: 0644]
src/MEDLoader/MeshFormatReader.hxx [new file with mode: 0644]
src/MEDLoader/MeshFormatWriter.cxx [new file with mode: 0644]
src/MEDLoader/MeshFormatWriter.hxx [new file with mode: 0644]
src/MEDLoader/Swig/MEDLoaderCommon.i
src/MEDLoader/libmesh5.cxx [new file with mode: 0644]
src/MEDLoader/libmesh5.hxx [new file with mode: 0644]

index 3f659f7b2ba4e92106a73f0920e8c9f419119263..8c54e4ab2061b03454b7134c7a157ba4a359a83e 100644 (file)
@@ -85,6 +85,10 @@ SET(medloader_SOURCES
   SauvMedConvertor.cxx
   SauvReader.cxx
   SauvWriter.cxx
+  MEDMESHConverterUtilities.cxx
+  MeshFormatReader.cxx
+  MeshFormatWriter.cxx
+  libmesh5.cxx
   )
 
 ADD_LIBRARY(medloader ${medloader_SOURCES})
diff --git a/src/MEDLoader/MEDMESHConverterUtilities.cxx b/src/MEDLoader/MEDMESHConverterUtilities.cxx
new file mode 100644 (file)
index 0000000..d58fa1c
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2021  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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 "MEDMESHConverterUtilities.hxx"
+
+#include "libmesh5.hxx"
+
+namespace MeshFormat
+{
+    bool isMeshExtensionCorrect( const std::string& fileName )
+    {
+        std::string ext;
+        {
+            auto pos(fileName.find_last_of('.'));
+            if(pos != std::string::npos)
+                ext = fileName.substr(pos);
+        }
+        switch ( ext.size() ) {
+        case 5:
+            return ( ext == ".mesh" || ext == ".solb" );
+        case 6:
+            return ( ext == ".meshb" );
+        case 4:
+            return ( ext == ".sol" );
+        }
+        return false;
+    }
+
+
+    Localizer::Localizer()
+    {
+        _locale = setlocale(LC_NUMERIC, NULL);
+        setlocale(LC_NUMERIC, "C");
+    }
+
+    Localizer::~Localizer()
+    {
+        setlocale(LC_NUMERIC, _locale.c_str() );
+    }
+}
+
+
diff --git a/src/MEDLoader/MEDMESHConverterUtilities.hxx b/src/MEDLoader/MEDMESHConverterUtilities.hxx
new file mode 100644 (file)
index 0000000..022eb03
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright (C) 2021  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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
+//
+
+#ifndef MEDMESHCONVERTERUTILITIES_HXX
+#define MEDMESHCONVERTERUTILITIES_HXX
+
+#include "MEDLoaderDefines.hxx"
+
+# include <string>
+# include <sstream>
+#include <iostream>
+# include <vector>
+#include <cstring>
+
+
+
+#define THROW_IK_EXCEPTION(text)                        \
+{                                                     \
+    std::ostringstream oss; oss << text;                \
+    throw INTERP_KERNEL::Exception(oss.str().c_str());  \
+}
+
+namespace MeshFormat
+{
+bool isMeshExtensionCorrect( const std::string& fileName );
+
+//~void closeMeshFile(const int gmfMeshID);
+
+enum Status {
+    DRS_OK,
+    DRS_EMPTY,          // a file contains no mesh with the given name
+    DRS_WARN_RENUMBER,  // a file has overlapped ranges of element numbers,
+    // so the numbers from the file are ignored
+    DRS_WARN_SKIP_ELEM, // some elements were skipped due to incorrect file data
+    DRS_WARN_DESCENDING, // some elements were skipped due to descending connectivity
+    DRS_FAIL            // general failure (exception etc.)
+};
+/*!
+ * \brief Class to generate string from any type
+ */
+class Comment : public std::string
+{
+    std::ostringstream _s ;
+
+public :
+
+    Comment():std::string("") {}
+
+    Comment(const Comment& c):std::string() {
+        _s << c.c_str() ;
+        this->std::string::operator=( _s.str() );
+    }
+
+    Comment & operator=(const Comment& c) {
+        _s << c.c_str() ;
+        this->std::string::operator=( _s.str() );
+        return *this;
+    }
+
+    template <class T>
+    Comment( const T &anything ) {
+        _s << anything ;
+        this->std::string::operator=( _s.str() );
+    }
+
+    template <class T>
+    Comment & operator<<( const T &anything ) {
+        _s << anything ;
+        this->std::string::operator=( _s.str() );
+        return *this ;
+    }
+
+    operator char*() const {
+        return (char*)c_str();
+    }
+
+    std::ostream& Stream() {
+        return _s;
+    }
+};
+/*!
+   * \brief Enforce freeing memory allocated by std::vector
+   */
+template <class TVECTOR>
+void FreeVector(TVECTOR& vec)
+{
+    TVECTOR v2;
+    vec.swap( v2 );
+}
+template <class TVECTOR>
+void CompactVector(TVECTOR& vec)
+{
+    TVECTOR v2( vec );
+    vec.swap( v2 );
+}
+
+class Localizer
+{
+    std::string _locale;
+public:
+    Localizer();
+    ~Localizer();
+};
+}
+
+
+#endif // MEDMESHCONVERTERUTILITIES_HXX
diff --git a/src/MEDLoader/MeshFormatReader.cxx b/src/MEDLoader/MeshFormatReader.cxx
new file mode 100644 (file)
index 0000000..7f405bb
--- /dev/null
@@ -0,0 +1,1000 @@
+// Copyright (C) 2021  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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 "MeshFormatReader.hxx"
+
+#include "MEDFileMesh.hxx"
+#include "MEDFileField.hxx"
+#include "MEDFileData.hxx"
+#include "MEDCouplingFieldDouble.hxx"
+#include "libmesh5.hxx"
+#include "MEDMESHConverterUtilities.hxx"
+#include <cstring>
+#include <fstream>
+
+namespace MEDCoupling {
+MeshFormatReader::MeshFormatReader():_myMeshName("MESH")
+{}  
+MeshFormatReader::MeshFormatReader(const std::string& meshFileName,
+                                   const std::vector<std::string>& fieldFileName):_myFile(meshFileName),
+                                   _myFieldFileNames(fieldFileName),
+                                   _myCurrentFileId(0),
+                                   _myMeshName("MESH")
+{}
+
+MeshFormatReader::~MeshFormatReader()
+{}
+
+MEDCoupling::MCAuto<MEDCoupling::MEDFileData> MeshFormatReader::loadInMedFileDS()
+{
+    _myStatus = perform();
+    if(_myStatus != MeshFormat::DRS_OK) return 0;
+
+    if ( !_uMesh->getName().c_str() || strlen( _uMesh->getName().c_str() ) == 0 )
+        _uMesh->setName( _myMeshName );
+    if ( _myFieldFileNames.size() ) performFields();
+
+
+    MEDCoupling::MCAuto< MEDCoupling::MEDFileMeshes > meshes = MEDCoupling::MEDFileMeshes::New();
+    _myMed = MEDCoupling::MEDFileData::New();
+    meshes->pushMesh( _uMesh );
+    _myMed->setMeshes( meshes );
+
+    if ( _fields ) _myMed->setFields( _fields );
+
+    return _myMed.retn();
+}
+
+//================================================================================
+/*!
+ * \brief Read a GMF file
+ */
+//================================================================================
+
+MeshFormat::Status MeshFormatReader::perform()
+{
+    MeshFormat::Localizer loc;
+
+    MeshFormat::Status status = MeshFormat::DRS_OK;
+
+
+    // open the file
+     _reader = MeshFormat::MeshFormatParser();
+    _myCurrentOpenFile = _myFile;
+    _myCurrentFileId = _reader.GmfOpenMesh( _myFile.c_str(), GmfRead, &_version, &_dim );
+    if ( !_myCurrentFileId )
+    {
+        if ( MeshFormat::isMeshExtensionCorrect( _myFile ))
+        {
+
+            return addMessage( MeshFormat::Comment("Can't open for reading ") << _myFile,
+                               /*fatal=*/true );
+        }
+        else
+            return addMessage( MeshFormat::Comment("Not '.mesh' or '.meshb' extension of file ") << _myFile,
+                               /*fatal=*/true );
+    }
+
+
+    // Read nodes
+
+
+    MEDCoupling::DataArrayDouble* coordArray = MEDCoupling::DataArrayDouble::New();
+    setNodes(coordArray);
+
+
+    int nbEdges = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfEdges);
+    int nbTria = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfTriangles);
+    int nbQuad = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfQuadrilaterals);
+    int nbTet = _reader.GmfStatKwd( _myCurrentFileId, MeshFormat::GmfTetrahedra );
+    int nbPyr = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfPyramids);
+    int nbHex = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfHexahedra);
+    int nbPrism = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfPrisms);
+
+    _dim1NbEl = nbEdges;
+    _dim2NbEl = nbTria + nbQuad;
+    _dim3NbEl = nbTet + nbPyr + nbHex + nbPrism;
+    bool okdim1 = (nbEdges > 0), okdim2= (_dim2NbEl > 0), okdim3= (_dim3NbEl > 0);
+
+    MEDCoupling::MEDCouplingUMesh* dimMesh1;
+    MEDCoupling::MEDCouplingUMesh* dimMesh2;
+    MEDCoupling::MEDCouplingUMesh* dimMesh3;
+
+    // dim 1
+    if (okdim1 ) {
+        dimMesh1 = MEDCoupling::MEDCouplingUMesh::New();
+        dimMesh1->setCoords( coordArray );
+        dimMesh1->allocateCells( nbEdges);
+        dimMesh1->setMeshDimension( 1 );
+    }
+    // dim 2
+    if (okdim2) {
+        dimMesh2 = MEDCoupling::MEDCouplingUMesh::New();
+        dimMesh2->setCoords( coordArray );
+        dimMesh2->allocateCells(_dim2NbEl);
+        dimMesh2->setMeshDimension( 2 );
+    }
+    // dim 3
+    if (okdim3) {
+        dimMesh3 = MEDCoupling::MEDCouplingUMesh::New();
+        dimMesh3->setCoords( coordArray );
+        dimMesh3->allocateCells(_dim3NbEl);
+        dimMesh3->setMeshDimension( 3 );
+    }
+
+    // Read elements
+
+    int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
+
+    /* Read edges */
+
+    if ( nbEdges)
+    {
+        setEdges(dimMesh1, nbEdges);
+        dimMesh1->decrRef();
+    }
+
+    /* Read triangles */
+    if (nbTria)
+    {
+        setTriangles(dimMesh2, nbTria);
+    }
+
+    /* Read quadrangles */
+    if (nbQuad)
+    {
+        setQuadrangles( dimMesh2, nbQuad);
+    }
+
+    if (okdim2 ) {
+        dimMesh2->finishInsertingCells();
+        _uMesh->setMeshAtLevel( 2 - _dim, dimMesh2 );
+        dimMesh2->sortCellsInMEDFileFrmt();
+        dimMesh2->decrRef();
+    }
+    /* Read terahedra */
+    if (  nbTet )
+    {
+        setTetrahedras( dimMesh3, nbTet);
+    }
+
+    /* Read pyramids */
+    if ( nbPyr )
+    {
+        setPyramids( dimMesh3, nbPyr);
+    }
+
+    /* Read hexahedra */
+    if ( nbHex )
+    {
+        setHexahedras(dimMesh3, nbHex);
+    }
+
+    /* Read prism */
+    //~const int prismIDShift = myMesh->GetMeshInfo().NbElements();
+    if ( nbPrism )
+    {
+        setPrisms(dimMesh3, nbPrism);
+    }
+
+    if (okdim3 ) {
+        dimMesh3->finishInsertingCells();
+        _uMesh->setMeshAtLevel( 3 - _dim, dimMesh3 );
+        dimMesh3->decrRef();
+    }
+
+    buildFamilies();
+    coordArray->decrRef();
+    _reader.GmfCloseMesh(_myCurrentFileId);
+    _myCurrentFileId = -1;
+    _myCurrentOpenFile ="";
+    return status;
+}
+
+MeshFormat::Status MeshFormatReader::performFields()
+{
+
+    MeshFormat::Status status = MeshFormat::DRS_OK;
+    _fields = MEDCoupling::MEDFileFields::New();
+
+
+    const MeshFormat::GmfKwdCod meshFormatSol[1] = { MeshFormat::GmfSolAtVertices};  // ONLY VERTEX SOL FOR NOW
+
+    int dim, version;
+    std::vector<std::string>::const_iterator fieldFileIt = _myFieldFileNames.begin();
+
+    for (; fieldFileIt !=_myFieldFileNames.end();  ++fieldFileIt)
+    {
+        _myCurrentOpenFile = *fieldFileIt;
+        _myCurrentFileId = _reader.GmfOpenMesh( fieldFileIt->c_str(), GmfRead, &version, &dim );
+        if ( !_myCurrentFileId )
+        {
+            if ( MeshFormat::isMeshExtensionCorrect( *fieldFileIt ))
+            {
+
+                return addMessage( MeshFormat::Comment("Can't open for reading ") << *fieldFileIt,
+                                   /*fatal=*/true );
+            }
+            else
+                return addMessage( MeshFormat::Comment("Not '.sol' or '.solb' extension of file ") << _myFile,
+                                   /*fatal=*/true );
+        }
+
+        if (version != _version)
+        {
+
+            addMessage( MeshFormat::Comment("Warning sol file version is different than mesh file version ") << *fieldFileIt,
+                               /*fatal=*/false );
+        }
+        if (dim != _dim)
+        {
+
+            return addMessage( MeshFormat::Comment("Error sol file must have same dimension as mesh file ") << *fieldFileIt,
+                               /*fatal=*/true );
+        }
+
+
+        MeshFormat::GmfKwdCod kwd = meshFormatSol[0];
+        int NmbSol, NmbTypes, NmbReals, TypesTab[ GmfMaxTyp ];
+        NmbSol = _reader.GmfStatKwd( _myCurrentFileId, kwd, &NmbTypes, &NmbReals, TypesTab );
+        if(NmbSol)
+        {
+
+            for(int i=0; i<NmbTypes; i++)
+            {
+                _reader.GmfGotoKwd(_myCurrentFileId, kwd);
+                switch(TypesTab[i])
+                {
+                case GmfSca:
+                {
+
+                    setFields(kwd, NmbSol, 1);
+                    break;
+                }
+                case GmfVec:
+                {
+
+                    setFields(kwd, NmbSol, dim);
+                    break;
+                }
+                case GmfSymMat :
+                {
+
+                    setFields(kwd, NmbSol, dim*(dim+1)/2 );
+                    break;
+                }
+                case GmfMat:
+                {
+
+                    setFields(kwd, NmbSol, dim*dim);
+                    break;
+                }
+                }
+
+            }
+
+
+
+        }
+
+  
+    
+        _reader.GmfCloseMesh(_myCurrentFileId);
+        _myCurrentFileId = -1;
+        _myCurrentOpenFile ="";
+    }
+
+}
+
+void MeshFormatReader::setFields( MeshFormat::GmfKwdCod kwd, int nmbSol, int nbComp)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayDouble> fieldValues =  MEDCoupling::DataArrayDouble::New();
+    fieldValues->alloc(nmbSol, nbComp);
+    double* values = fieldValues->getPointer();
+
+    int ref;
+    double *val = new double[nbComp];
+
+    bool isOnAll = (_uMesh->getNumberOfNodes()== nmbSol);
+
+
+    for(int i = 1; i<= nmbSol; i++)
+    {
+        callParserGetLin(kwd, val, nbComp, &ref);
+
+        std::copy(val, val+nbComp, values);
+
+        values+=nbComp;
+    }
+    values=fieldValues->getPointer(); // to delete
+
+    delete []val;
+
+    MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> timeStamp;
+    MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tsField =  MEDCoupling::MEDFileFieldMultiTS::New();
+    MEDCoupling::MCAuto<MEDCoupling::MEDCouplingUMesh> dimMesh ;
+    int  dimRel;
+    MEDCoupling::TypeOfField typeOfField;
+    setTypeOfFieldAndDimRel(kwd,  &typeOfField,  &dimRel );
+
+    timeStamp = MEDCoupling::MEDCouplingFieldDouble::New(typeOfField);
+    dimMesh = _uMesh->getMeshAtLevel(dimRel);
+
+
+    timeStamp->setMesh( dimMesh );
+    std::string name = "Field_on_Vertex";
+    timeStamp->setName(name);
+    timeStamp->setArray(fieldValues);
+    // set an order
+    const int nbTS = tsField->getNumberOfTS();
+    if ( nbTS > 0 )
+        timeStamp->setOrder( nbTS );
+
+    // add the time-stamp
+    timeStamp->checkConsistencyLight();
+
+    if (isOnAll)
+    {
+        tsField->appendFieldNoProfileSBT( timeStamp );
+    }
+
+
+    _fields->pushField( tsField);
+
+}
+
+void MeshFormatReader::setMeshName(const std::string& theMeshName)
+{
+    _myMeshName = theMeshName;
+}
+
+std::string MeshFormatReader::getMeshName() const
+{
+    return _myMeshName;
+}
+
+
+void MeshFormatReader::setFile(const std::string& theFileName)
+{
+    _myFile = theFileName;
+}
+
+void MeshFormatReader::setFieldFileNames(const std::vector<std::string>& theFieldFileNames)
+{
+    _myFieldFileNames = theFieldFileNames;
+}
+std::vector<std::string> MeshFormatReader::getFieldFileNames() const
+{
+    return _myFieldFileNames;
+}
+
+MeshFormat::Status MeshFormatReader::addMessage(const std::string& msg,
+        const bool         isFatal/*=false*/)
+{
+    if ( isFatal )
+        _myErrorMessages.clear(); // warnings are useless if a fatal error encounters
+
+    _myErrorMessages.push_back( msg );
+
+    //~MESSAGE(msg);
+#ifdef _DEBUG_
+    std::cout << msg << std::endl;
+#endif
+    return ( _myStatus = isFatal ? MeshFormat::DRS_FAIL : MeshFormat::DRS_WARN_SKIP_ELEM );
+}
+
+void MeshFormatReader::backward_shift(mcIdType* tab, int size)
+{
+    for(int i = 0; i<size; i++) tab[i] = tab[i]-1;
+}
+
+
+MeshFormat::Status MeshFormatReader::setNodes( MEDCoupling::DataArrayDouble* coordArray)
+{
+
+    MeshFormat::Status status = MeshFormat::DRS_OK;
+    int nbNodes = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfVertices);
+    if ( nbNodes < 1 )
+        return addMessage( "No nodes in the mesh", /*fatal=*/true );
+
+    _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfVertices);
+
+    int ref;
+    _uMesh = MEDCoupling::MEDFileUMesh::New();
+    coordArray->alloc( nbNodes, _dim );
+    double* coordPrt = coordArray->getPointer();
+    std::vector<double> nCoords (_dim+2, 0.0) ;
+
+    double* coordPointer  = &nCoords[0];
+
+    if ( _version != GmfFloat )
+    {
+        double x, y, z;
+
+        for ( int i = 1; i <= nbNodes; ++i )
+        {
+            _dim == 2 ? _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfVertices, &x, &y, &ref) : \
+            _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfVertices, &x, &y, &z, &ref);
+            nCoords[0] = x;
+            nCoords[1] = y;
+            nCoords[2] = z;
+            std::copy(coordPointer, coordPointer+_dim, coordPrt);
+            MeshFormatElement e(MeshFormat::GmfVertices, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 1);
+            coordPrt += _dim;
+
+        }
+
+    }
+    else
+    {
+        float x, y, z;
+
+        for ( int i = 1; i <= nbNodes; ++i )
+        {
+            _dim == 2 ? _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfVertices, &x, &y, &ref) :
+            _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfVertices, &x, &y, &z, &ref);
+            nCoords[0] = x;
+            nCoords[1] = y;
+            nCoords[2] = z;
+            std::copy(coordPointer, coordPointer+_dim, coordPrt);
+            MeshFormatElement e(MeshFormat::GmfVertices, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 1);
+            coordPrt += _dim;
+        }
+    }
+    _uMesh->setCoords( coordArray );
+
+    return status;
+
+}
+
+
+void MeshFormatReader::setEdges( MEDCoupling::MEDCouplingUMesh* dimMesh1, int nbEdges)
+{
+
+    int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
+    int ref;
+    // read extra vertices for quadratic edges
+    std::vector<int> quadNodesAtEdges( nbEdges + 1, -1 );
+    if ( int nbQuadEdges = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtEdges))
+    {
+        _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtEdges);
+        for ( int i = 1; i <= nbQuadEdges; ++i )
+        {
+            _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtEdges, &iN[0], &iN[1], &iN[2]);
+            if ( iN[1] >= 1 )
+                quadNodesAtEdges[ iN[0] ] = iN[2];
+        }
+    }
+    // create edges
+    _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfEdges);
+    for ( int i = 1; i <= nbEdges; ++i )
+    {
+        _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfEdges, &iN[0], &iN[1], &ref);
+        const int midN = quadNodesAtEdges[ i ];
+        if ( midN > 0 )
+        {
+
+            mcIdType nodalConnPerCell[3] = {iN[0], iN[1], midN};
+            backward_shift(nodalConnPerCell, 3);
+            dimMesh1->insertNextCell(INTERP_KERNEL::NORM_SEG3, 3,nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfEdges, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 1 -_dim);
+        }
+        else
+        {
+
+            mcIdType nodalConnPerCell[2] = {iN[0], iN[1]};
+            backward_shift(nodalConnPerCell, 2);
+            dimMesh1->insertNextCell(INTERP_KERNEL::NORM_SEG2, 2,nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfEdges, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 1 -_dim);
+        }
+    }
+
+    dimMesh1->finishInsertingCells();
+    dimMesh1->sortCellsInMEDFileFrmt();
+    _uMesh->setMeshAtLevel( 1 - _dim, dimMesh1 );
+}
+
+void MeshFormatReader::setTriangles(MEDCoupling::MEDCouplingUMesh* dimMesh2, int nbTria)
+{
+    int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
+    int ref;
+    // read extra vertices for quadratic triangles
+    std::vector< std::vector<int> > quadNodesAtTriangles( nbTria + 1 );
+    if ( int nbQuadTria = _reader.GmfStatKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtTriangles ))
+    {
+        _reader.GmfGotoKwd( _myCurrentFileId, MeshFormat::GmfExtraVerticesAtTriangles );
+        for ( int i = 1; i <= nbQuadTria; ++i )
+        {
+            _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtTriangles,
+                             &iN[0], &iN[1], &iN[2], &iN[3], &iN[4],
+                             &iN[5]); // iN[5] - preview TRIA7
+            if ( iN[0] <= nbTria )
+            {
+                std::vector<int>& nodes = quadNodesAtTriangles[ iN[0] ];
+                nodes.insert( nodes.end(), & iN[2], & iN[5+1] );
+                nodes.resize( iN[1] );
+            }
+        }
+    }
+
+    // create triangles
+
+    _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfTriangles);
+
+    for ( int i = 1; i <= nbTria; ++i )
+    {
+        _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfTriangles, &iN[0], &iN[1], &iN[2], &ref);
+        std::vector<int>& midN = quadNodesAtTriangles[ i ];
+        if ( midN.size() >= 3 )
+        {
+
+            mcIdType nodalConnPerCell[6] = {iN[0], iN[1], iN[2], midN[0], midN[1], midN[2]};
+            backward_shift(nodalConnPerCell, 6);
+            dimMesh2->insertNextCell(INTERP_KERNEL::NORM_TRI6, 6, nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfTriangles, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 2 -_dim);
+        }
+        else
+        {
+            mcIdType nodalConnPerCell[3] = {iN[0], iN[1], iN[2]};
+            backward_shift(nodalConnPerCell, 3);
+            dimMesh2->insertNextCell(INTERP_KERNEL::NORM_TRI3,3,nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfTriangles, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 2 -_dim);
+        }
+        if ( !midN.empty() ) MeshFormat::FreeVector( midN );
+    }
+
+
+}
+
+void MeshFormatReader::setQuadrangles( MEDCoupling::MEDCouplingUMesh* dimMesh2, int nbQuad)
+{
+    int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
+    int ref;
+    // read extra vertices for quadratic quadrangles
+    std::vector< std::vector<int> > quadNodesAtQuadrilaterals( nbQuad + 1 );
+    if ( int nbQuadQuad = _reader.GmfStatKwd( _myCurrentFileId, MeshFormat::GmfExtraVerticesAtQuadrilaterals ))
+    {
+        _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtQuadrilaterals);
+        for ( int i = 1; i <= nbQuadQuad; ++i )
+        {
+            _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtQuadrilaterals,
+                             &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6]);
+            if ( iN[0] <= nbQuad )
+            {
+                std::vector<int>& nodes = quadNodesAtQuadrilaterals[ iN[0] ];
+                nodes.insert( nodes.end(), & iN[2], & iN[6+1] );
+                nodes.resize( iN[1] );
+            }
+        }
+    }
+    // create quadrangles
+    _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfQuadrilaterals);
+    for ( int i = 1; i <= nbQuad; ++i )
+    {
+        _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfQuadrilaterals, &iN[0], &iN[1], &iN[2], &iN[3], &ref);
+        std::vector<int>& midN = quadNodesAtQuadrilaterals[ i ];
+        if ( midN.size() == 8-4 ) // QUAD8
+        {
+            mcIdType nodalConnPerCell[8] = {iN[0], iN[1], iN[2], iN[3],
+                                            midN[0], midN[1], midN[2], midN[3]
+                                           };
+            backward_shift(nodalConnPerCell, 8);
+            dimMesh2->insertNextCell(INTERP_KERNEL::NORM_QUAD8,8, nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfQuadrilaterals, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 2 -_dim);
+        }
+        else if ( midN.size() > 8-4 ) // QUAD9
+        {
+            mcIdType nodalConnPerCell[9] = {iN[0], iN[1], iN[2], iN[3],
+                                            midN[0], midN[1], midN[2], midN[3], midN[4]
+                                           };
+            backward_shift(nodalConnPerCell, 9);
+            dimMesh2->insertNextCell(INTERP_KERNEL::NORM_QUAD9,9, nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfQuadrilaterals, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 2 -_dim);
+        }
+        else // QUAD4
+        {
+            mcIdType nodalConnPerCell[4] = {iN[0], iN[1], iN[2], iN[3]};
+            backward_shift(nodalConnPerCell, 4);
+            dimMesh2->insertNextCell(INTERP_KERNEL::NORM_QUAD4, 4, nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfQuadrilaterals, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 2 -_dim);
+        }
+        if ( !midN.empty() ) MeshFormat::FreeVector( midN );
+    }
+
+}
+
+void MeshFormatReader::setTetrahedras( MEDCoupling::MEDCouplingUMesh* dimMesh3, int nbTet)
+{
+    int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
+    int ref;
+    // read extra vertices for quadratic tetrahedra
+    std::vector< std::vector<int> > quadNodesAtTetrahedra( nbTet + 1 );
+    if ( int nbQuadTetra = _reader.GmfStatKwd( _myCurrentFileId, MeshFormat::GmfExtraVerticesAtTetrahedra ))
+    {
+        _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtTetrahedra);
+        for ( int i = 1; i <= nbQuadTetra; ++i )
+        {
+            _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtTetrahedra,
+                             &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7]);
+            if ( iN[0] <= nbTet )
+            {
+                std::vector<int>& nodes = quadNodesAtTetrahedra[ iN[0] ];
+                nodes.insert( nodes.end(), & iN[2], & iN[7+1] );
+                nodes.resize( iN[1] );
+            }
+        }
+    }
+    // create tetrahedra
+    _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfTetrahedra);
+    for ( int i = 1; i <= nbTet; ++i )
+    {
+        _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfTetrahedra, &iN[0], &iN[1], &iN[2], &iN[3], &ref);
+        std::vector<int>& midN = quadNodesAtTetrahedra[ i ];
+        if ( midN.size() >= 10-4 ) // TETRA10
+        {
+            mcIdType nodalConnPerCell[10] = {iN[0], iN[2], iN[1], iN[3],
+                                             midN[2], midN[1], midN[0], midN[3], midN[5], midN[4]
+                                            };
+            backward_shift(nodalConnPerCell, 10);
+            dimMesh3->insertNextCell(INTERP_KERNEL::NORM_TETRA10, 10,nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfTetrahedra, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 3 -_dim);
+        }
+        else // TETRA4
+        {
+            mcIdType nodalConnPerCell[4] = {iN[0], iN[2], iN[1], iN[3]};
+            backward_shift(nodalConnPerCell, 4);
+            dimMesh3->insertNextCell(INTERP_KERNEL::NORM_TETRA4,4, nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfTetrahedra, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 3 -_dim);
+        }
+        if ( !midN.empty() ) MeshFormat::FreeVector( midN );
+    }
+
+}
+
+
+void MeshFormatReader::setPyramids( MEDCoupling::MEDCouplingUMesh* dimMesh3, int nbPyr)
+{
+    int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
+    int ref;
+    _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfPyramids);
+    for ( int i = 1; i <= nbPyr; ++i )
+    {
+        _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfPyramids, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &ref);
+        mcIdType nodalConnPerCell[5] = {iN[3], iN[2], iN[1], iN[0], iN[4]};
+        backward_shift(nodalConnPerCell, 5);
+        dimMesh3->insertNextCell(INTERP_KERNEL::NORM_PYRA5, 5,nodalConnPerCell);
+        MeshFormatElement e(MeshFormat::GmfPyramids, i-1);
+        _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 3 -_dim);
+    }
+
+}
+
+
+void MeshFormatReader::setHexahedras( MEDCoupling::MEDCouplingUMesh* dimMesh3, int nbHex)
+{
+    int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
+    int ref;
+    // read extra vertices for quadratic hexahedra
+    std::vector< std::vector<int> > quadNodesAtHexahedra( nbHex + 1 );
+    if ( int nbQuadHexa = _reader.GmfStatKwd( _myCurrentFileId, MeshFormat::GmfExtraVerticesAtHexahedra ))
+    {
+        _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtHexahedra);
+        for ( int i = 1; i <= nbQuadHexa; ++i )
+        {
+            _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtHexahedra, &iN[0], &iN[1], // Hexa Id, Nb extra vertices
+                             &iN[2], &iN[3], &iN[4], &iN[5],
+                             &iN[6], &iN[7], &iN[8], &iN[9],
+                             &iN[10], &iN[11], &iN[12], &iN[13], // HEXA20
+                             &iN[14],
+                             &iN[15], &iN[16], &iN[17], &iN[18],
+                             &iN[19],
+                             &iN[20]);                          // HEXA27
+            if ( iN[0] <= nbHex )
+            {
+                std::vector<int>& nodes = quadNodesAtHexahedra[ iN[0] ];
+                nodes.insert( nodes.end(), & iN[2], & iN[20+1] );
+                nodes.resize( iN[1] );
+            }
+        }
+    }
+    // create hexhedra
+
+
+    _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfHexahedra);
+    for ( int i = 1; i <= nbHex; ++i )
+    {
+        _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfHexahedra, &iN[0], &iN[1], &iN[2], &iN[3],
+                         &iN[4], &iN[5], &iN[6], &iN[7], &ref);
+        std::vector<int>& midN = quadNodesAtHexahedra[ i ];
+        if ( midN.size() == 20-8 ) // HEXA20
+        {
+            mcIdType nodalConnPerCell[20] = {iN[0], iN[3], iN[2], iN[1],
+                                             iN[4], iN[7], iN[6], iN[5],
+                                             midN[3], midN[2], midN[1], midN[0],
+                                             midN[7], midN[6], midN[5], midN[4],
+                                             midN[8], midN[11], midN[10], midN[9]
+                                            };
+            backward_shift(nodalConnPerCell, 20);
+            dimMesh3->insertNextCell(INTERP_KERNEL::NORM_HEXA20,20, nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfHexahedra, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 3 -_dim);
+
+
+        }
+        else if ( midN.size() >= 27-8 ) // HEXA27
+        {
+            mcIdType nodalConnPerCell[27] = {iN[0], iN[3], iN[2], iN[1],
+                                             iN[4], iN[7], iN[6], iN[5],
+                                             midN[3], midN[2], midN[1], midN[0],
+                                             midN[7], midN[6], midN[5], midN[4],
+                                             midN[8], midN[11], midN[10], midN[9],
+                                             midN[12],
+                                             midN[16], midN[15], midN[14], midN[13],
+                                             midN[17],
+                                             midN[18]
+                                            };
+            backward_shift(nodalConnPerCell, 27);
+            dimMesh3->insertNextCell(INTERP_KERNEL::NORM_HEXA27,27, nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfHexahedra, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 3 -_dim);
+
+        }
+        else // HEXA8
+        {
+            mcIdType nodalConnPerCell[8] = {iN[0], iN[3], iN[2], iN[1],
+                                            iN[4], iN[7], iN[6], iN[5]
+                                           };
+            backward_shift(nodalConnPerCell, 8);
+            dimMesh3->insertNextCell(INTERP_KERNEL::NORM_HEXA8,8, nodalConnPerCell);
+            MeshFormatElement e(MeshFormat::GmfHexahedra, i-1);
+            _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 3 -_dim);
+
+        }
+        if ( !midN.empty() ) MeshFormat::FreeVector( midN );
+    }
+
+
+}
+
+
+
+void MeshFormatReader::setPrisms(MEDCoupling::MEDCouplingUMesh* dimMesh3, int nbPrism)
+{
+    int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
+    int ref;
+    _reader.GmfGotoKwd(_myCurrentFileId, MeshFormat::GmfPrisms);
+    for ( int i = 1; i <= nbPrism; ++i )
+    {
+        _reader.GmfGetLin(_myCurrentFileId, MeshFormat::GmfPrisms, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref);
+        mcIdType nodalConnPerCell[8] = {iN[0], iN[2], iN[1], iN[3], iN[5], iN[4]};
+        backward_shift(nodalConnPerCell, 8);
+        dimMesh3->insertNextCell(INTERP_KERNEL::NORM_PENTA6, 6,nodalConnPerCell);
+        MeshFormatElement e(MeshFormat::GmfPrisms, i-1);
+        _fams.insert(std::pair <int, MeshFormatElement> (ref, e), 3 -_dim);
+
+    }
+
+
+}
+
+void MeshFormatReader::callParserGetLin( MeshFormat::GmfKwdCod kwd,  double* val, int valSize, int* ref)
+{
+    switch(valSize)
+    {
+    case 1:
+    {
+        _reader.GmfGetLin(_myCurrentFileId, kwd, &val[0], ref);
+        break;
+    }
+    case 2:
+    {
+        _reader.GmfGetLin(_myCurrentFileId, kwd, &val[0], &val[1], ref);
+        break;
+    }
+    case 3:
+    {
+        _reader.GmfGetLin(_myCurrentFileId, kwd, &val[0], &val[1], &val[2], ref);
+        break;
+    }
+    case 4:
+    {
+        _reader.GmfGetLin(_myCurrentFileId, kwd, &val[0], &val[1], &val[2], &val[3], ref);
+        break;
+    }
+    case 6:
+    {
+        _reader.GmfGetLin(_myCurrentFileId, kwd, &val[0], &val[1], &val[2], &val[3], &val[4], &val[5], ref);
+        break;
+    }
+    case 9:
+    {
+        _reader.GmfGetLin(_myCurrentFileId, kwd, &val[0], &val[1], &val[2], &val[3], &val[4], &val[5], &val[6], &val[7], &val[8], ref);
+        break;
+    }
+    }
+}
+
+void MeshFormatReader::setTypeOfFieldAndDimRel(MeshFormat::GmfKwdCod kwd, MEDCoupling::TypeOfField* typeOfField, int* dimRel )
+{
+    switch (kwd)
+    {
+    case MeshFormat::GmfSolAtVertices :
+    {
+        *typeOfField = MEDCoupling::ON_NODES;
+        *dimRel = 1 ;
+        break;
+    }
+    case MeshFormat::GmfSolAtEdges :
+    {
+        *typeOfField = MEDCoupling::ON_CELLS;
+        *dimRel = 1 - _dim ;
+        break;
+    }
+    case MeshFormat::GmfSolAtTriangles :
+    case MeshFormat::GmfSolAtQuadrilaterals :
+    {
+        *typeOfField = MEDCoupling::ON_CELLS;
+        *dimRel = 2 - _dim;
+        break;
+    }
+    case MeshFormat::GmfSolAtTetrahedra :
+    case MeshFormat::GmfSolAtPrisms :
+    case MeshFormat::GmfSolAtHexahedra :
+    {
+        *typeOfField = MEDCoupling::ON_CELLS;
+        *dimRel = 3 - _dim;
+        break;
+    }
+    }
+}
+
+
+INTERP_KERNEL::NormalizedCellType MeshFormatReader::toMedType(MeshFormat::GmfKwdCod kwd)
+{
+    INTERP_KERNEL::NormalizedCellType type;
+    //~switch (kwd)
+    //~{
+    //~case MeshFormat::GmfEdges :
+    //~{
+
+    //~type = INTERP_KERNEL::NORM_SEG2;
+    //~break;
+    //~}
+    //~case MeshFormat::GmfTriangles :
+    //~{
+    //~type = INTERP_KERNEL::NORM_TRI3;
+    //~break;
+    //~}
+    //~case MeshFormat::GmfQuadrilaterals :
+    //~{
+    //~type = INTERP_KERNEL::NORM_QUAD;
+    //~break;
+    //~}
+    //~case MeshFormat::GmfSolAtTetrahedra :
+    //~case MeshFormat::GmfSolAtPrisms :
+    //~case MeshFormat::GmfSolAtHexahedra :
+    //~{
+    //~*typeOfField = MEDCoupling::ON_CELLS;
+    //~*dimRel = 3 - _dim;
+    //~break;
+    //~}
+    //~}
+    return type;
+}
+
+
+void MeshFormatReader::buildFamilies()
+{
+    buildNodesFamilies();
+    buildCellsFamilies();
+}
+
+void MeshFormatReader::buildCellsFamilies()
+{
+    std::vector<int> levs =  _uMesh->getNonEmptyLevels();
+    for (size_t iDim = 0; iDim<levs.size(); iDim++ )
+    {
+        int dimRelMax = levs[iDim];
+        std::map <int, std::vector<MeshFormatElement>* > famDim = _fams.getMapAtLevel(dimRelMax);
+        std::map <int, std::vector<MeshFormatElement>* >::const_iterator _meshFormatFamsIt = famDim.begin();
+        std::vector< const MEDCoupling::DataArrayIdType* > fams;
+        MEDCoupling::DataArrayIdType* cellIds = MEDCoupling::DataArrayIdType::New();
+        cellIds->alloc(_uMesh->getSizeAtLevel(dimRelMax), 1);
+        cellIds->fillWithZero();
+
+        for(; _meshFormatFamsIt!= famDim.end(); ++_meshFormatFamsIt)
+        {
+            const int famId = _meshFormatFamsIt->first;
+            std::string famName ="FromMeshGemsFormatAttributFamily_"+std::to_string(famId);
+            std::vector <MeshFormatElement>* cellsInFam = _meshFormatFamsIt->second;
+            if (!famId) continue;
+            std::vector <MeshFormatElement>::iterator cellsInFamIt = cellsInFam->begin();
+
+            _uMesh->addFamily(famName, famId);
+            for ( ; cellsInFamIt !=cellsInFam->end(); ++cellsInFamIt)
+            {
+                cellIds->setIJ(cellsInFamIt->_id, 0, famId);
+            }
+
+        }
+        _uMesh->setFamilyFieldArr(dimRelMax, cellIds->deepCopy());
+        cellIds->decrRef();
+
+
+    }  
+}
+
+void MeshFormatReader::buildNodesFamilies()
+{
+  std::vector<int> levs =  _uMesh->getNonEmptyLevels();
+     int dimRelMax = 1;
+  std::map <int, std::vector<MeshFormatElement>* > famDim = _fams.getMapAtLevel(dimRelMax);
+  std::map <int, std::vector<MeshFormatElement>* >::const_iterator _meshFormatFamsIt = famDim.begin();
+  std::vector< const MEDCoupling::DataArrayIdType* > fams;
+  MEDCoupling::DataArrayIdType* cellIds = MEDCoupling::DataArrayIdType::New();
+  cellIds->alloc(_uMesh->getSizeAtLevel(dimRelMax), 1);
+  cellIds->fillWithZero();
+
+  for(; _meshFormatFamsIt!= famDim.end(); ++_meshFormatFamsIt)
+  {
+    const int famId = _meshFormatFamsIt->first;
+    if (!famId) continue; 
+    bool thisIsACellFamily = false;
+    
+    for (size_t iDim = 0; iDim<levs.size(); iDim++ )
+    {
+      int dimMesh = levs[iDim];
+      std::map <int, std::vector<MeshFormatElement>* > famDimAtLevel = _fams.getMapAtLevel(dimMesh);  
+      std::map <int, std::vector<MeshFormatElement>* >::iterator famDimAtLevelId = famDimAtLevel.find(famId);  
+      if (famDimAtLevelId != famDimAtLevel.end())
+      {
+        thisIsACellFamily = true;
+        break;
+      }
+      
+    }
+    
+    if (thisIsACellFamily) continue;
+    std::string famName ="FromMeshGemsFormatAttributFamily_"+std::to_string(famId);
+    std::vector <MeshFormatElement>* cellsInFam = _meshFormatFamsIt->second;
+    std::vector <MeshFormatElement>::iterator cellsInFamIt = cellsInFam->begin();
+
+    _uMesh->addFamily(famName, famId);
+    for ( ; cellsInFamIt !=cellsInFam->end(); ++cellsInFamIt)
+    {
+      cellIds->setIJ(cellsInFamIt->_id, 0, famId);
+    }
+
+  }
+  _uMesh->setFamilyFieldArr(dimRelMax, cellIds->deepCopy());
+  cellIds->decrRef();
+}
+}
diff --git a/src/MEDLoader/MeshFormatReader.hxx b/src/MEDLoader/MeshFormatReader.hxx
new file mode 100644 (file)
index 0000000..15e3836
--- /dev/null
@@ -0,0 +1,220 @@
+// Copyright (C) 2021  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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
+//
+
+#ifndef MESHFORMATREADER_HXX
+#define MESHFORMATREADER_HXX
+
+#include <vector>
+#include <string>
+#include <map>
+#include <algorithm>
+#include <utility>
+#include <iterator>
+#include "MCAuto.hxx"
+#include "InterpKernelException.hxx"
+#include "NormalizedUnstructuredMesh.hxx"
+#include "MCType.hxx"
+#include "MEDMESHConverterUtilities.hxx"
+#include "libmesh5.hxx"
+
+#include <fstream>
+#include <features.h>
+namespace MEDCoupling
+{
+class DataArrayDouble;
+class DataArrayInt;
+class MEDFileData;
+class MEDFileFields;
+class MEDFileFieldMultiTS;
+class MEDFileUMesh;
+class MEDCouplingUMesh;
+
+
+struct MeshFormatElement {
+    MeshFormatElement(int type, int id=0):_type(type), _id(id) {}
+    int _type;
+    int _id;
+
+    inline friend bool operator==(const MeshFormatElement& a, const MeshFormatElement&b ) {
+        return ((a._type == b._type) && (a._id == b._id));
+    }
+};
+
+struct MeshFormatFamily {
+
+    std::map <int, std::vector<MeshFormatElement>* > _meshFormatFams;
+    std::map <int, std::vector<MeshFormatElement>* > _meshFormatFams_0;
+    std::map <int, std::vector<MeshFormatElement>* > _meshFormatFams_1;
+    std::map <int, std::vector<MeshFormatElement>* > _meshFormatFams_2;
+    std::map <int, std::vector<MeshFormatElement>* > _meshFormatFamsNodes;
+
+public:
+    void insert(std::pair<int, MeshFormatElement> addToFamily, int dimRelMax)
+    {
+        insertPairInMap(_meshFormatFams, addToFamily);
+        insertPairInMap(getMapAtLevel(dimRelMax), addToFamily);
+    }
+private:
+    void insertPairInMap(std::map <int, std::vector<MeshFormatElement>* >& aMap, std::pair<int, MeshFormatElement> addToFamily)
+    {
+        std::map <int, std::vector<MeshFormatElement>* >::iterator it = aMap.find(addToFamily.first);
+        if (it!= aMap.end())
+        {
+            aMap[addToFamily.first]->push_back(addToFamily.second);
+        }
+        else
+        {
+            std::vector <MeshFormatElement>* tmpVec = new std::vector <MeshFormatElement> ;
+            tmpVec->push_back(addToFamily.second);
+            aMap.insert(std::pair <int, std::vector <MeshFormatElement>* > (addToFamily.first, tmpVec) );
+
+        }
+
+    }
+public:
+    void remove(std::pair<int, MeshFormatElement> removeFromFamily, int dimRelMax)
+    {
+        removePairFromMap(_meshFormatFams, removeFromFamily);
+        removePairFromMap(getMapAtLevel(dimRelMax), removeFromFamily);
+
+    }
+private:
+    void removePairFromMap(std::map <int, std::vector<MeshFormatElement>* > & aMap, const std::pair<int, MeshFormatElement> removeFromFamily)
+    {
+
+        if (!aMap.size() ) return;
+        std::map <int, std::vector<MeshFormatElement>* >::iterator itTmp = aMap.find(removeFromFamily.first);
+        if (itTmp == aMap.end()) return;
+        else
+        {
+            std::vector <MeshFormatElement>* tmpVec2 = aMap[removeFromFamily.first];
+#if __GNUC_PREREQ(4,9)
+            std::vector <MeshFormatElement>::const_iterator itt2;
+#else
+            std::vector <MeshFormatElement>::iterator itt2;
+#endif
+            const MeshFormatElement e = removeFromFamily.second;
+            itt2 = std::find(tmpVec2->begin(), tmpVec2->end(), e);
+            if (itt2 != tmpVec2->end())
+                tmpVec2->erase(itt2);
+
+            if (!tmpVec2->size())
+            {
+                delete tmpVec2;
+                aMap.erase(removeFromFamily.first);
+            }
+        }
+    }
+public:
+    std::map <int, std::vector<MeshFormatElement>* > & getMapAtLevel(int dimRelMax)
+    {
+        switch(dimRelMax)
+        {
+        case 0 :
+            return  _meshFormatFams_0;
+            break;
+        case -1 :
+            return  _meshFormatFams_1;
+            break;
+        case -2 :
+            return  _meshFormatFams_2;
+            break;
+        case 1 :
+            return  _meshFormatFamsNodes;
+            break;
+        }
+    }
+public:
+    ~MeshFormatFamily()
+    {
+
+        freeMap(_meshFormatFams);
+        freeMap(_meshFormatFams_0);
+        freeMap(_meshFormatFams_1);
+        freeMap(_meshFormatFams_2);
+        freeMap(_meshFormatFamsNodes);
+
+    }
+
+private:
+    void freeMap(std::map <int, std::vector<MeshFormatElement>* > & aMap)
+    {
+        std::map <int, std::vector<MeshFormatElement>* >::iterator it = aMap.begin();
+        for (; it !=aMap.end(); ++it) delete it->second;
+    }
+
+};
+class MeshFormatReader
+{
+public :
+    MEDLOADER_EXPORT MeshFormatReader();
+    MEDLOADER_EXPORT MeshFormatReader(const std::string& meshFileName, const std::vector<std::string>& fieldFileName);
+    MEDLOADER_EXPORT ~MeshFormatReader();
+  
+    MEDLOADER_EXPORT MEDCoupling::MCAuto<MEDCoupling::MEDFileData> loadInMedFileDS() ;
+    MEDLOADER_EXPORT void setMeshName(const std::string& theMeshName);
+    MEDLOADER_EXPORT std::string getMeshName() const;
+    MEDLOADER_EXPORT void setFile(const std::string& theFileName);
+    MEDLOADER_EXPORT void setFieldFileNames(const std::vector<std::string>& theFieldFileNames);
+    MEDLOADER_EXPORT std::vector<std::string> getFieldFileNames() const;
+    MEDLOADER_EXPORT std::vector< std::string > getErroMessage() const;
+
+private :
+
+    MeshFormat::Status addMessage(const std::string& msg, const bool isFatal=false);
+    MeshFormat::Status perform();
+    MeshFormat::Status performFields();
+    MeshFormat::Status setNodes(MEDCoupling::DataArrayDouble* coordArray);
+    void setEdges(MEDCoupling::MEDCouplingUMesh* dimMesh1, int nbEdges);
+    void setTriangles( MEDCoupling::MEDCouplingUMesh* dimMesh2, int nbTria);
+    void setQuadrangles( MEDCoupling::MEDCouplingUMesh* dimMesh2, int nbQuad);
+    void setTetrahedras( MEDCoupling::MEDCouplingUMesh* dimMesh3, int nbTet);
+    void setPyramids(MEDCoupling::MEDCouplingUMesh* dimMesh3, int nbPyr);
+    void setHexahedras(MEDCoupling::MEDCouplingUMesh* dimMesh3, int nbHex);
+    void setPrisms(MEDCoupling::MEDCouplingUMesh* dimMesh3, int nbPrism);
+    void callParserGetLin( MeshFormat::GmfKwdCod kwd,  double* val, int valSize, int* ref);
+    void setTypeOfFieldAndDimRel(MeshFormat::GmfKwdCod kwd, MEDCoupling::TypeOfField* typeOfField, int* dimRel );
+    void backward_shift(MEDCoupling::mcIdType*, int size);
+    void setFields( MeshFormat::GmfKwdCod kwd, int nmbSol, int nbComp);
+    INTERP_KERNEL::NormalizedCellType toMedType(MeshFormat::GmfKwdCod kwd);
+    void buildFamilies();
+    void buildNodesFamilies();
+    void buildCellsFamilies();
+
+    std::string _myFile;
+    MeshFormat::MeshFormatParser _reader;
+    std::string _myCurrentOpenFile;
+    int _myCurrentFileId;
+    std::string _myMeshName;
+    std::vector<std::string> _myFieldFileNames;
+    int _dim, _version;
+    std::vector< std::string > _myErrorMessages;
+    MeshFormat::Status                     _myStatus;
+    MEDCoupling::MCAuto<MEDCoupling::MEDFileData> _myMed;
+    MEDCoupling::MCAuto<MEDCoupling::MEDFileUMesh> _uMesh;
+    MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> _fields;
+    // map id family --element
+    MeshFormatFamily _fams;
+
+    int _dim1NbEl;
+    int _dim2NbEl;
+    int _dim3NbEl;
+};
+}
+#endif //MESHFORMATREADER_HXX
diff --git a/src/MEDLoader/MeshFormatWriter.cxx b/src/MEDLoader/MeshFormatWriter.cxx
new file mode 100644 (file)
index 0000000..346e4e1
--- /dev/null
@@ -0,0 +1,1137 @@
+// Copyright (C) 2021  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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 "MeshFormatWriter.hxx"
+#include "MEDFileMesh.hxx"
+#include "MEDFileField.hxx"
+#include "MEDFileData.hxx"
+#include "MEDCouplingFieldDouble.hxx"
+#include "libmesh5.hxx"
+#include "MEDMESHConverterUtilities.hxx"
+#include <cstring>
+#include <algorithm>
+#include <map>
+#include <cstdlib>
+#include <fstream>
+
+
+namespace MEDCoupling {
+  
+MeshFormatWriter::MeshFormatWriter()
+{}
+MeshFormatWriter::MeshFormatWriter(const std::string& meshFileName,
+                                   const std::vector<std::string>& fieldFileNames):_meshFileName(meshFileName),
+                                   _fieldFileNames(fieldFileNames)
+{}
+MeshFormatWriter::~MeshFormatWriter()
+{}
+void MeshFormatWriter::setMeshFileName(const std::string& meshFileName)
+{
+    _meshFileName = meshFileName;
+}
+void MeshFormatWriter::setFieldFileNames(const std::vector<std::string>& fieldFileNames)
+{
+    _fieldFileNames = fieldFileNames;
+}
+void MeshFormatWriter::setMEDFileDS(MEDCoupling::MEDFileData* mfd)
+{
+
+    if(!mfd)
+    {
+        addMessage( MeshFormat::Comment(" MEDFileData is nullptr! ") << _meshFileName, /*fatal=*/true );
+        return;
+    }
+    if ( !mfd->getNumberOfMeshes())
+    {
+        addMessage( MeshFormat::Comment("No Mesh in MEDFileData! ") << _meshFileName, /*fatal=*/true );
+        return;
+    }
+    if ( mfd->getNumberOfMeshes() > 1)
+    {
+        addMessage( MeshFormat::Comment("More than One Mesh in File! ") << _meshFileName, /*fatal=*/true );
+        return;
+    }
+
+    MEDCoupling::MEDFileMeshes* meshes  = mfd->getMeshes();
+    _mesh  = meshes->getMeshAtPos(0);
+
+    _mesh->incrRef();
+    MEDCoupling::MEDFileFields* fields = mfd->getFields();
+
+    for (int i = 0; i<fields->getNumberOfFields(); i++ )
+    {
+        MEDCoupling::MEDFileAnyTypeFieldMultiTS* field = fields->getFieldAtPos(i);
+        MEDCoupling::MEDFileFieldMultiTS * f = dynamic_cast<MEDCoupling::MEDFileFieldMultiTS *>(field);
+        _fields.push_back(f);
+    }
+
+
+}
+
+void MeshFormatWriter::write()
+{
+
+    MeshFormat::Localizer loc;
+
+    MEDCoupling::MCAuto<MEDCoupling::MEDCouplingMesh > mesh = _mesh->getMeshAtLevel( 1 );
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh = mesh->buildUnstructured();
+    _dim = umesh->getSpaceDimension();
+
+    if (_dim != 2 && _dim != 3)
+    {
+        addMessage( MeshFormat::Comment("Only 3D or 2D mesh allowed! ") << _meshFileName, /*fatal=*/true );
+        return ;
+    }
+
+
+    _version = sizeof(double) < 8 ? 1 : 2;
+    _writer = MeshFormat::MeshFormatParser();
+    _myCurrentOpenFile = _meshFileName;
+    _myCurrentFileId = _writer.GmfOpenMesh( _meshFileName.c_str(), GmfWrite, _version, _dim );
+    if ( !_myCurrentFileId )
+    {
+        if ( MeshFormat::isMeshExtensionCorrect( _meshFileName ))
+        {
+            addMessage( MeshFormat::Comment("Can't open for writing ") << _meshFileName, /*fatal=*/true );
+            return;
+        }
+
+        else
+        {
+            addMessage( MeshFormat::Comment("Not '.mesh' or '.meshb' extension of file ") << _meshFileName, /*fatal=*/true );
+            return;
+        }
+
+    }
+
+
+    perform();
+    _writer.GmfCloseMesh(_myCurrentFileId);
+    _myCurrentFileId = -1;
+    _myCurrentOpenFile = "";
+    if (_fields.size()) performFields();
+
+
+}
+
+MeshFormat::Status MeshFormatWriter::perform()
+{
+
+
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingMesh > mesh1;
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh1;
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingMesh > mesh2;
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2;
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingMesh > mesh3;
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3;
+
+    std::vector<int> dims = _mesh->getNonEmptyLevelsExt();
+    int dim = _mesh->getMeshDimension();
+    bool threeDElements = false;
+    bool twoDElements = false;
+    bool OneDElements = false;
+    if (dims.size() != 0)
+    {
+        bool maxLevelDimElments = ( std::find(dims.begin(), dims.end(), 0) != dims.end() );
+        bool nextToMaxLevelDimElments = ( std::find(dims.begin(), dims.end(), -1) != dims.end() );
+        bool nextToNextToMaxLevelDimElments = (std::find(dims.begin(), dims.end(), -2) != dims.end() );
+        threeDElements = (dim == 3) ? maxLevelDimElments : false ;
+        twoDElements =  (dim == 3) ? nextToMaxLevelDimElments : maxLevelDimElments ;
+        OneDElements = (dim == 3) ? nextToNextToMaxLevelDimElments : nextToMaxLevelDimElments;
+    }
+
+    MEDCoupling::mcIdType nbEdgesNSEG2 = 0;
+    MEDCoupling::mcIdType nbEdgesNSEG3 = 0;
+    MEDCoupling::mcIdType nbTRI3 = 0;
+    MEDCoupling::mcIdType nbTRI6 = 0;
+    MEDCoupling::mcIdType nbQUAD4 = 0;
+    MEDCoupling::mcIdType nbQUAD8 = 0;
+    MEDCoupling::mcIdType nbQUAD9 = 0;
+    MEDCoupling::mcIdType nbTETRA4 = 0;
+    MEDCoupling::mcIdType nbTETRA10 = 0;
+    MEDCoupling::mcIdType nbPYRA5 = 0;
+    MEDCoupling::mcIdType nbHEXA8 = 0;
+    MEDCoupling::mcIdType nbHEXA20 = 0;
+    MEDCoupling::mcIdType nbHEXA27 = 0;
+    MEDCoupling::mcIdType nbPENTA6 = 0;
+
+    if (OneDElements)
+    {
+        mesh1 = _mesh->getMeshAtLevel( 1-dim );
+        umesh1 = mesh1->buildUnstructured();
+        nbEdgesNSEG2 = umesh1->getNumberOfCellsWithType(INTERP_KERNEL::NORM_SEG2);
+
+        nbEdgesNSEG3 = umesh1->getNumberOfCellsWithType(INTERP_KERNEL::NORM_SEG3);
+
+    }
+    if (twoDElements)
+    {
+        mesh2 = _mesh->getMeshAtLevel( 2-dim );
+        umesh2 = mesh2->buildUnstructured();
+        nbTRI3 = umesh2->getNumberOfCellsWithType(INTERP_KERNEL::NORM_TRI3);
+
+        nbTRI6 = umesh2->getNumberOfCellsWithType(INTERP_KERNEL::NORM_TRI6);
+
+        nbQUAD4 = umesh2->getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
+
+        nbQUAD8 = umesh2->getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD8);
+
+        nbQUAD9 = umesh2->getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD9);
+
+    }
+    if (threeDElements)
+    {
+
+        mesh3 = _mesh->getMeshAtLevel( 3-dim );
+        umesh3 = mesh3->buildUnstructured();
+        nbTETRA4 = umesh3->getNumberOfCellsWithType(INTERP_KERNEL::NORM_TETRA4);
+
+        nbTETRA10 = umesh3->getNumberOfCellsWithType(INTERP_KERNEL::NORM_TETRA10);
+
+        nbPYRA5 = umesh3->getNumberOfCellsWithType(INTERP_KERNEL::NORM_PYRA5);
+
+        nbHEXA8 = umesh3->getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
+
+        nbHEXA20 = umesh3->getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA20);
+
+        nbHEXA27 = umesh3->getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA27);
+
+        nbPENTA6 = umesh3->getNumberOfCellsWithType(INTERP_KERNEL::NORM_PENTA6);
+
+    }
+
+
+
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingMesh > mesh0 = _mesh->getMeshAtLevel(1);
+    MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh0 = mesh0->buildUnstructured();
+
+    // nodes
+    getNodes(umesh0);
+
+    // edges SEG2
+    if ( nbEdgesNSEG2 > 0)
+    {
+        getNSEG2( nbEdgesNSEG2, umesh1);
+    }
+    //~// nodes of quadratic edges SEG3
+    if ( nbEdgesNSEG3 > 0)
+    {
+        getNSEG3( nbEdgesNSEG3, umesh1);
+    }
+
+    // triangles TRI3
+    if ( nbTRI3 > 0)
+    {
+        getTRI3( nbTRI3, umesh2);
+    }
+
+    // nodes of quadratic triangles
+    // triangles TRI6
+    if ( nbTRI6 > 0)
+    {
+        getTRI6( nbTRI6, umesh2);
+
+    }
+    //~// quadrangles QUAD4
+    if ( nbQUAD4 > 0)
+    {
+        getQUAD4(nbQUAD4, umesh2);
+    }
+
+    //~// quadrangles quadratic QUAD8
+    if ( nbQUAD8 > 0)
+    {
+        getQUAD8( nbQUAD8, umesh2);
+    }
+
+    //~// quadrangles quadratic QUAD9
+    if ( nbQUAD9 > 0)
+    {
+        getQUAD9( nbQUAD9, umesh2);
+    }
+
+    // terahedra TETRA4
+    if ( nbTETRA4 > 0)
+    {
+        getTETRA4( nbTETRA4, umesh3);
+    }
+    //~terahedra TETRA10
+    if ( nbTETRA10 > 0)
+    {
+        getTETRA10( nbTETRA10, umesh3);
+    }
+
+    //~// pyramids 5
+    if ( nbPYRA5 > 0)
+    {
+        getPYRA5(nbPYRA5, umesh3);
+    }
+    //~// hexahedra 8
+    if ( nbHEXA8 > 0)
+    {
+        getHEXA8( nbHEXA8, umesh3);
+    }
+
+    //~// hexahedra 20
+    if ( nbHEXA20 > 0)
+    {
+        getHEXA20( nbHEXA20, umesh3);
+    }
+
+    //~// hexahedra 27
+    if ( nbHEXA27 > 0)
+    {
+        getHEXA27 (nbHEXA27, umesh3);
+    }
+
+    // prism
+    if ( nbPENTA6 > 0)
+    {
+        getPENTA6(nbPENTA6, umesh3);
+    }
+
+    linkFamilyToCells();
+    writeCells();
+
+
+    return MeshFormat::DRS_OK;
+}
+
+
+MeshFormat::Status MeshFormatWriter::performFields()
+{
+
+    MeshFormat::Status status = MeshFormat::Status::DRS_OK;
+
+    if (_fields.size() != _fieldFileNames.size() )
+    {
+        addMessage( MeshFormat::Comment(" Number of fields and number of input *.sol files must be equal ") << _meshFileName, /*fatal=*/true );
+        status = MeshFormat::Status::DRS_FAIL;
+        return status;
+    }
+
+
+    int  dim = _mesh->getMeshDimension();  // dim mesh  field lying to
+    std::vector<std::string>::const_iterator fieldFileIt = _fieldFileNames.begin();
+    int iField = 0;
+    std::vector<int> levs {0} ;
+    for (; fieldFileIt !=_fieldFileNames.end();  ++fieldFileIt)
+    {
+        // Open files
+        _myCurrentOpenFile = *fieldFileIt;
+
+        MEDCoupling::MEDFileFieldMultiTS* f = _fields[iField];
+
+        if(!f)
+            continue;// why???
+        if ( f->getMeshName() == _mesh->getName() )
+        {
+
+            std::vector< std::vector<MEDCoupling::TypeOfField> > fTypes = f->getTypesOfFieldAvailable();
+            std::vector< std::pair<int,int> >  iters = f->getIterations();
+            const std::vector<std::string>& compInfo = f->getInfo();
+            std::pair<int,int> it = iters[0];
+
+            //~// Open File for writing
+            _myCurrentFileId = _writer.GmfOpenMesh( fieldFileIt->c_str(), GmfWrite, _version, _dim );
+
+            if ( fTypes[0].size() == 1 && fTypes[0][0] == MEDCoupling::ON_NODES )
+            {
+                setFieldOnNodes(f, it.first,  it.second, compInfo.size());
+            }
+            else
+            {
+                setFieldOnCells( f, it.first,  it.second, levs );
+            }
+            //~// Close File
+            _writer.GmfCloseMesh( _myCurrentFileId );
+        }
+
+
+        iField++;
+    }
+
+    return status;
+}
+
+MeshFormat::Status MeshFormatWriter::setFieldOnNodes(MEDCoupling::MEDFileFieldMultiTS * f, int iteration, int order, size_t compSize)
+{
+
+
+    std::vector<INTERP_KERNEL::NormalizedCellType> types;
+    std::vector< std::vector<MEDCoupling::TypeOfField> > typesF;
+    std::vector< std::vector<std::string> > pfls, locs;
+    std::vector< std::vector< std::pair<mcIdType,mcIdType> > > valsVec;
+    valsVec = f->getFieldSplitedByType( iteration, order, _mesh->getName().c_str(),
+                                        types, typesF, pfls, locs);
+    // believe that there can be only one type in a nodal field,
+    // so do not perform a loop on types
+    const MEDCoupling::DataArrayDouble* valsArray = f->getUndergroundDataArray(iteration, order);
+    int typTab[] = { getGmfSolKwd((int)compSize, _dim) };
+    _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfSolAtVertices, (int)valsVec[0][0].second, 1, typTab);
+    double* valTab0 = new double[compSize];
+    double* valTab;
+    for ( size_t i = valsVec[0][0].first; i < (std::size_t)valsVec[0][0].second; ++i )
+    {
+
+        for ( size_t j = 0; j < compSize; ++j )
+            valTab0[j] = valsArray->getIJ( i, j );
+            
+    if (compSize == 9 || compSize == 4){ // full matrix ==>uper triangular matrix
+      extractSymetricTensor(valTab0, valTab);
+      _writer.GmfSetLin( _myCurrentFileId, MeshFormat::GmfSolAtVertices, valTab);
+      delete [] valTab;
+      
+    }
+    else  
+        _writer.GmfSetLin( _myCurrentFileId, MeshFormat::GmfSolAtVertices, valTab0);
+
+    }
+    delete [] valTab0;
+
+
+
+}
+
+MeshFormat::Status MeshFormatWriter::setFieldOnCells(MEDCoupling::MEDFileFieldMultiTS * f, int iteration, int order, std::vector<int> levs )
+{
+
+    int  dim = _mesh->getMeshDimension();  // dim mesh  field lying to
+    int absDim = f->getNonEmptyLevels(iteration, order,  f->getMeshName(), levs);
+
+    MEDCoupling::MEDCouplingFieldDouble**  cellToNodeFldb  = new MEDCoupling::MEDCouplingFieldDouble* [(int)levs.size()] ;
+    MEDCoupling::MEDCouplingFieldDouble**  fldb  = new MEDCoupling::MEDCouplingFieldDouble* [(int)levs.size()] ;
+
+    for (size_t k = 0; k<levs.size(); k++) fldb[k] = f->field( iteration, order,_mesh );
+
+    // turn it node discretization
+    for (size_t l = 0; l < levs.size(); l++) cellToNodeFldb[l] = fldb[l]->cellToNodeDiscretization() ;
+
+    for(size_t j =0; j < levs.size(); j++ )
+    {
+
+        const mcIdType pointsNumber = cellToNodeFldb[j]->getNumberOfTuples();
+        const mcIdType nbComp = (int) cellToNodeFldb[j]->getNumberOfComponents() ;
+
+        MEDCoupling::DataArrayDouble* timeStamp = cellToNodeFldb[j]->getArray();
+        double* values = timeStamp->getPointer();
+
+        int typ = getGmfSolKwd((int)nbComp, _dim) ;
+        if(typ == -1)
+        {
+            addMessage( MeshFormat::Comment(" error with Number of Component   ") << nbComp, /*fatal=*/true );
+            return MeshFormat::Status::DRS_FAIL;
+        }
+
+        int typTab[] = {typ};
+        _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfSolAtVertices, pointsNumber, 1, typTab);
+
+
+        double *valTab;
+        for (int i = 0; i < pointsNumber ; i++ )
+        {
+
+            double valTab0[10]; //max 3x3 matrix +1 for safety ;)
+
+            std::copy(values, values+nbComp, valTab0);
+
+            if (nbComp == 9 || nbComp == 4) // full matrix ==>uper triangular matrix
+            {
+        extractSymetricTensor(valTab0, valTab);
+                _writer.GmfSetLin( _myCurrentFileId, MeshFormat::GmfSolAtVertices, valTab);
+                delete [] valTab;
+            }
+            else //sym mat, scalar or vec
+            {
+                valTab = new double[nbComp];
+                std::copy(valTab0, valTab0+nbComp, valTab);
+                _writer.GmfSetLin( _myCurrentFileId, MeshFormat::GmfSolAtVertices, valTab);
+                delete [] valTab;
+            }
+            values+=nbComp;
+
+        }
+
+
+    }
+
+    for(size_t i = 0; i < levs.size(); i++ )  fldb[i]->decrRef();
+    for(size_t i = 0; i < levs.size(); i++ )  cellToNodeFldb[i]->decrRef();
+    delete [] cellToNodeFldb;
+    delete [] fldb;
+
+}
+ /*\
+ |*| extract the upper triangular matrix  of fullTensor
+ |*| if _dim == 2 fill symTensor with values at index 0, 1 & 3 of fullTensor
+ |*| |x0 x1|   
+ |*| |x2 x3|  
+ |*| if _dim == 3 fill symTensor with values at index 0, 1, 2, 4, 5 & 8 of fullTensor
+ |*| |x0 x1 x2|
+ |*| |x3 x4 x5|
+ |*| |x6 x7 x8|
+ \*/
+void MeshFormatWriter::extractSymetricTensor(double fullTensor[], double*& symTensor)
+{
+     symTensor = new double[_dim*(_dim+1)/2];
+  for (int ii =0; ii<_dim; ii++)
+    for (int jj =ii; jj<_dim; jj++)
+    {
+      int kk = _dim*(_dim-1)/2- (_dim-ii)*(_dim-ii-1)/2+jj;
+      symTensor[kk] = fullTensor[ii+jj*_dim];
+    }  
+}
+int MeshFormatWriter::getGmfSolKwd(const int nbComp, const int dim)
+{
+    if (nbComp== 1) return GmfSca;
+    else if( dim == nbComp) return GmfVec;
+    else if (dim*(dim+1)/2 == nbComp || dim*dim == nbComp ) return GmfSymMat;
+    //~else if (dim*dim == nbComp) return GmfMat; // Not valid in mg-adapt if not sym
+    else  return -1;
+}
+bool MeshFormatWriter::checkFileName()
+{
+    bool ret = true;
+    return ret;
+}
+bool MeshFormatWriter::checkFieldFileName()
+{
+    bool ret = true;
+    return ret;
+
+}
+
+std::string MeshFormatWriter::getMeshFileName() const
+{
+    return _meshFileName;
+}
+
+
+std::vector<std::string> MeshFormatWriter::getFieldFileNames() const
+{
+    return _fieldFileNames;
+}
+
+MeshFormat::Status MeshFormatWriter::addMessage(const std::string& msg,
+        const bool         isFatal/*=false*/)
+{
+    if ( isFatal )
+        _myErrorMessages.clear(); // warnings are useless if a fatal error encounters
+
+    _myErrorMessages.push_back( msg );
+
+    //~MESSAGE(msg);
+#ifdef _DEBUG_
+    std::cout << msg << std::endl;
+#endif
+    return ( _myStatus = isFatal ? MeshFormat::DRS_FAIL : MeshFormat::DRS_WARN_SKIP_ELEM );
+}
+
+
+void MeshFormatWriter::forward_shift(std::vector<MEDCoupling::mcIdType> &conn)
+{
+    std::vector<MEDCoupling::mcIdType>::iterator it = conn.begin();
+    for (; it != conn.end(); ++it) *it = *it+1;
+}
+
+
+void MeshFormatWriter::getNodes(MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh0)
+{
+    MEDCoupling::mcIdType nbNodes = 0;
+    nbNodes = umesh0->getNumberOfNodes();
+
+
+    // nodes
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayDouble> coordArray = umesh0->getCoordinatesAndOwner();
+    double* coordPrt = coordArray->getPointer();
+    _writer.GmfSetKwd( _myCurrentFileId, MeshFormat::GmfVertices, nbNodes );
+    double xyz[3];
+    int j = (int)nbNodes;
+
+    int idNode = 0;
+
+    while ( j >0 )
+    {
+
+        std::copy(coordPrt, coordPrt+_dim, xyz);
+
+        MeshFormatNode e(xyz[0], xyz[1], xyz[2], idNode);
+        _idNodeToNode.insert(std::pair <int, MeshFormatNode> (idNode, e));
+
+        coordPrt+= _dim;
+        j--;
+        idNode++;
+    }
+    linkFamilyToNodes();
+    std::map <int, MeshFormatNode>::iterator itNode = _idNodeToNode.begin();
+    for (; itNode!= _idNodeToNode.end(); ++itNode)
+        _dim == 3?  _writer.GmfSetLin( _myCurrentFileId, MeshFormat::GmfVertices, itNode->second.xyz[0],
+                     itNode->second.xyz[1], itNode->second.xyz[2], std::abs(itNode->second._famId) ) :
+                      _writer.GmfSetLin( _myCurrentFileId, MeshFormat::GmfVertices, itNode->second.xyz[0],
+                     itNode->second.xyz[1], std::abs(itNode->second._famId) );
+}
+
+
+void MeshFormatWriter::getNSEG2(MEDCoupling::mcIdType nbEdgesNSEG2, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh1)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh1->giveCellsWithType(INTERP_KERNEL::NORM_SEG2);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh1->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+
+        MeshFormatCell e(INTERP_KERNEL::NORM_SEG2, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_SEG2, idCellToCell) );
+}
+
+
+void MeshFormatWriter::getNSEG3( MEDCoupling::mcIdType nbEdgesNSEG3, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh1)
+{
+
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh1->giveCellsWithType(INTERP_KERNEL::NORM_SEG3);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh1->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_SEG3, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_SEG3, idCellToCell) );
+}
+
+
+void MeshFormatWriter::getTRI3( MEDCoupling::mcIdType nbTRI3, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_TRI3);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh2->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_TRI3, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_TRI3, idCellToCell) );
+}
+
+
+void MeshFormatWriter::getTRI6( MEDCoupling::mcIdType nbTRI6, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_TRI6);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh2->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_TRI6, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_TRI6, idCellToCell) );
+}
+
+void MeshFormatWriter::getQUAD4( MEDCoupling::mcIdType nbQUAD4, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_QUAD4);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh2->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_QUAD4, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_QUAD4, idCellToCell) );
+}
+
+void MeshFormatWriter::getQUAD8(MEDCoupling::mcIdType nbQUAD8, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_QUAD8);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh2->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_QUAD8, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_QUAD8, idCellToCell) );
+}
+
+void MeshFormatWriter::getQUAD9(MEDCoupling::mcIdType nbQUAD9, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_QUAD9);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh2->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_QUAD9, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_QUAD9, idCellToCell) );
+}
+
+void MeshFormatWriter::getTETRA4(MEDCoupling::mcIdType nbTETRA4, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_TETRA4);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh3->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_TETRA4, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_TETRA4, idCellToCell) );
+}
+
+void MeshFormatWriter::getTETRA10(MEDCoupling::mcIdType nbTETRA10, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_TETRA10);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh3->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_TETRA10, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_TETRA10, idCellToCell) );
+}
+
+void MeshFormatWriter::getPYRA5(MEDCoupling::mcIdType nbPYRA5, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_PYRA5);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh3->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_PYRA5, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_PYRA5, idCellToCell) );
+}
+
+void MeshFormatWriter::getHEXA8(MEDCoupling::mcIdType nbHEXA8, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_HEXA8);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh3->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_HEXA8, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_HEXA8, idCellToCell) );
+}
+void MeshFormatWriter::getHEXA20(MEDCoupling::mcIdType nbHEXA20, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_HEXA20);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh3->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_HEXA20, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_HEXA20, idCellToCell) );
+}
+void MeshFormatWriter::getHEXA27(MEDCoupling::mcIdType nbHEXA27, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_HEXA27);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh3->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_HEXA27, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_HEXA27, idCellToCell) );
+}
+
+void MeshFormatWriter::getPENTA6(MEDCoupling::mcIdType nbPENTA6, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3)
+{
+
+    MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_PENTA6);
+    std::map<int, MeshFormatCell> idCellToCell;
+    for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ )
+    {
+        std::vector<MEDCoupling::mcIdType> conn;
+        umesh3->getNodeIdsOfCell(*it,  conn) ;
+        forward_shift(conn);
+        MeshFormatCell e(INTERP_KERNEL::NORM_PENTA6, (int)*it);
+        e.setConn(conn);
+        idCellToCell.insert(std::pair <int, MeshFormatCell> (*it, e));
+    }
+    _typeToIdCellToCell.insert(std::pair <INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >(INTERP_KERNEL::NORM_PENTA6, idCellToCell) );
+}
+
+
+void MeshFormatWriter::linkFamilyToNodes()
+{
+
+    std::map<std::string,mcIdType> famInfos =  _mesh->getFamilyInfo();
+    std::map<std::string,mcIdType>::const_iterator famIt =  famInfos.begin();
+    for (; famIt != famInfos.end(); ++famIt)
+    {
+        if(!famIt->second) continue; //FAMILLE_ZERO
+        MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> nodeIds =  _mesh->getNodeFamilyArr(famIt->first);
+        const MEDCoupling::mcIdType * nodeIdsIt = nodeIds->begin(), * famIDEnd = nodeIds->end();
+        for(; nodeIdsIt< famIDEnd; ++nodeIdsIt) {
+
+            std::map <int, MeshFormatNode>::iterator itNode = _idNodeToNode.find((int)*nodeIdsIt);
+            if (itNode == _idNodeToNode.end()) continue;
+            else itNode->second._famId =(int) famIt->second;
+
+
+        }
+    }
+}
+
+
+
+void MeshFormatWriter::linkFamilyToCells()
+{
+
+    std::vector<int> levs =  _mesh->getNonEmptyLevels();
+    for (size_t iDim = 0; iDim < levs.size(); iDim++ )
+    {
+        int meshDimRelToMax = levs[iDim];
+        MEDCoupling::MCAuto< MEDCoupling::MEDCouplingMesh > mesh = _mesh->getMeshAtLevel( meshDimRelToMax);
+        MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh0 = mesh->buildUnstructured();
+        const MEDCoupling::DataArrayIdType * famIds = _mesh->getFamilyFieldAtLevel(meshDimRelToMax);
+        const MEDCoupling::mcIdType * famID = famIds->begin(), *famIDEnd = famIds->end();
+        for (; famID < famIDEnd; ++famID)
+        {
+            if (!(*famID)) continue; // "FAMILLE_ZERO"
+            std::string famName = _mesh->getFamilyNameGivenId(*famID);
+            MEDCoupling::MCAuto<MEDCoupling::DataArrayIdType> cellIds =  _mesh->getFamilyArr( meshDimRelToMax, famName);
+            const MEDCoupling::mcIdType * cellIdsIt = cellIds->begin(), *cellIDEnd = cellIds->end();
+            for(; cellIdsIt< cellIDEnd; ++cellIdsIt)
+            {
+                INTERP_KERNEL::NormalizedCellType type = umesh0->getTypeOfCell(*cellIdsIt); //TODO
+                std::map<INTERP_KERNEL::NormalizedCellType, std::map <int, MeshFormatCell> >::iterator itCellMap = _typeToIdCellToCell.find(type);
+                if (itCellMap == _typeToIdCellToCell.end()) continue;
+                else
+                {
+                    std::map <int, MeshFormatCell>::iterator itCell = itCellMap->second.find((int)*cellIdsIt);
+                    if (itCell == itCellMap->second.end()) continue;
+                    else itCell->second._famId = (int)*famID;
+                }
+
+            }
+
+
+
+        }
+    }
+}
+void MeshFormatWriter::writeCells()
+{
+
+    std::map < INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> >::iterator typeCellMapIt = _typeToIdCellToCell.begin();
+    for (; typeCellMapIt!= _typeToIdCellToCell.end(); ++typeCellMapIt)
+    {
+        std::map<int, MeshFormatCell>::iterator cellMapIt = typeCellMapIt->second.begin();
+        switch (typeCellMapIt->first)
+        {
+        case INTERP_KERNEL::NORM_SEG2 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfEdges, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfEdges, conn[0], conn[1], std::abs(cellMapIt->second._famId) );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_SEG3 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfEdges, (int)typeCellMapIt->second.size());
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfEdges, conn[0], conn[1], std::abs(cellMapIt->second._famId) );
+            }
+            cellMapIt = typeCellMapIt->second.begin();
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtEdges, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtEdges, cellMapIt->first+1, 1, conn[2] );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_TRI3 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfTriangles, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfTriangles, conn[0], conn[1], conn[2], std::abs(cellMapIt->second._famId) );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_TRI6 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfTriangles, (int)typeCellMapIt->second.size());
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfTriangles, conn[0], conn[1], conn[2], std::abs(cellMapIt->second._famId) );
+            }
+
+            cellMapIt = typeCellMapIt->second.begin();
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtTriangles, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtTriangles, cellMapIt->first+1, 3, conn[3], conn[4], conn[5] );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_QUAD4 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfQuadrilaterals, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfQuadrilaterals, conn[0], conn[1], conn[2], conn[3], std::abs(cellMapIt->second._famId) );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_QUAD8 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfQuadrilaterals, (int)typeCellMapIt->second.size());
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfQuadrilaterals, conn[0], conn[1], conn[2], conn[3], std::abs(cellMapIt->second._famId) );
+            }
+            cellMapIt = typeCellMapIt->second.begin();
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtQuadrilaterals, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtQuadrilaterals, cellMapIt->first+1, 4, conn[4], conn[5],
+                                  conn[6], conn[7] );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_QUAD9 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfQuadrilaterals, (int)typeCellMapIt->second.size());
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfQuadrilaterals, conn[0], conn[1], conn[2], conn[3], std::abs(cellMapIt->second._famId) );
+            }
+            cellMapIt = typeCellMapIt->second.begin();
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtQuadrilaterals, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtQuadrilaterals,cellMapIt->first+1, 5, conn[4], conn[5],
+                                  conn[6], conn[7], conn[8] );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_TETRA4 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfTetrahedra, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfTetrahedra, conn[0], conn[2], conn[1], conn[3],  std::abs(cellMapIt->second._famId) );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_TETRA10 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtTetrahedra, (int)typeCellMapIt->second.size());
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfTetrahedra, conn[0], conn[2], conn[1], conn[3], std::abs(cellMapIt->second._famId) );
+            }
+            cellMapIt = typeCellMapIt->second.begin();
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfTetrahedra, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtTetrahedra, cellMapIt->first+1, 6, conn[6], conn[5],
+                                  conn[4], conn[7], conn[8], conn[9] );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_PYRA5 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfPyramids, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfPyramids, conn[3], conn[2], conn[1], conn[0], conn[4], std::abs(cellMapIt->second._famId) );
+
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_HEXA8 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfHexahedra, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfHexahedra, conn[0], conn[3], conn[2], conn[1], conn[4], conn[7], conn[6], conn[5], std::abs(cellMapIt->second._famId) );
+
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_HEXA20 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfHexahedra, (int)typeCellMapIt->second.size());
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfHexahedra, conn[0], conn[3], conn[2], conn[1],
+                                  conn[4], conn[7], conn[6], conn[5], std::abs(cellMapIt->second._famId) );
+            }
+            cellMapIt = typeCellMapIt->second.begin();
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtHexahedra, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtHexahedra,  cellMapIt->first+1, 12, conn[11], conn[10], conn[9],
+                                  conn[8], conn[15], conn[14], conn[13], conn[12], conn[16], conn[19], conn[18], conn[17] );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_HEXA27 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfHexahedra, (int)typeCellMapIt->second.size());
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtHexahedra, conn[0], conn[3], conn[2], conn[1],
+                                  conn[4], conn[7], conn[6], conn[5], std::abs(cellMapIt->second._famId) );
+            }
+            cellMapIt = typeCellMapIt->second.begin();
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtHexahedra, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfExtraVerticesAtHexahedra, cellMapIt->first+1, 19, conn[11], conn[10], conn[9],
+                                  conn[8], conn[15], conn[14], conn[13], conn[12], conn[16], conn[19], conn[18], conn[17],
+                                  conn[20], conn[24], conn[23], conn[22], conn[21], conn[25], conn[26], std::abs(cellMapIt->second._famId) );
+            }
+            break;
+        }
+        case INTERP_KERNEL::NORM_PENTA6 :
+        {
+
+            _writer.GmfSetKwd(_myCurrentFileId, MeshFormat::GmfPrisms, (int)typeCellMapIt->second.size());
+
+            for (; cellMapIt != typeCellMapIt->second.end(); ++cellMapIt)
+            {
+                std::vector<MEDCoupling::mcIdType> conn = cellMapIt->second.conn;
+                _writer.GmfSetLin(_myCurrentFileId, MeshFormat::GmfPrisms, conn[0], conn[2], conn[1], conn[3], conn[5], conn[4], std::abs(cellMapIt->second._famId) );
+            }
+            break;
+        }
+        }
+    }
+}
+}
diff --git a/src/MEDLoader/MeshFormatWriter.hxx b/src/MEDLoader/MeshFormatWriter.hxx
new file mode 100644 (file)
index 0000000..6b609d6
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright (C) 2021  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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
+//
+
+#ifndef MESHFORMATWRITER_HXX
+#define MESHFORMATWRITER_HXX
+
+#include <vector>
+#include <string>
+#include <string>
+#include "MCAuto.hxx"
+#include "InterpKernelException.hxx"
+#include "NormalizedUnstructuredMesh.hxx"
+#include "MCType.hxx"
+#include "MEDMESHConverterUtilities.hxx"
+#include "libmesh5.hxx"
+
+#include "MEDFileMesh.hxx"
+#include <fstream>
+
+namespace MEDCoupling
+{
+class DataArrayDouble;
+class DataArrayInt;
+class MEDFileData;
+class MEDFileFields;
+class MEDFileFieldMultiTS;
+class MEDFileUMesh;
+
+
+struct MeshFormatNode {
+    MeshFormatNode(double x, double y, double z=0, int id=0, int famId=0): _id(id), _famId(famId) {
+        xyz[0] = x;
+        xyz[1] = y;
+        xyz[2] = z;
+    }
+    int _id;
+    int _famId;
+    double xyz[3];
+
+    //~inline friend bool operator==(const MeshFormatNode& a, const MeshFormatNode&b ) { return ((a._type == b._type) && (a._id == b._id));}
+};
+
+struct MeshFormatCell {
+    MeshFormatCell(INTERP_KERNEL::NormalizedCellType  type, int id=0, int famId=0):_type(type), _id(id), _famId(famId) {}
+    INTERP_KERNEL::NormalizedCellType  _type;
+    int _id;
+    int _famId;
+    void setConn(const std::vector<MEDCoupling::mcIdType> cpy)
+    {
+        conn.clear();
+        std::copy(cpy.begin(), cpy.end(), std::back_inserter(conn));
+    }
+    std::vector<MEDCoupling::mcIdType> conn;
+};
+
+
+class MeshFormatWriter
+{
+public :
+    MEDLOADER_EXPORT MeshFormatWriter();
+    MEDLOADER_EXPORT MeshFormatWriter(const std::string& meshFileName, const std::vector<std::string>& fieldFileNames);
+    MEDLOADER_EXPORT ~MeshFormatWriter();
+    MEDLOADER_EXPORT void setMeshFileName(const std::string& meshFileName);
+    MEDLOADER_EXPORT std::string getMeshFileName() const;
+    MEDLOADER_EXPORT void setFieldFileNames(const std::vector<std::string>& fieldFileNames);
+    MEDLOADER_EXPORT std::vector<std::string> getFieldFileNames() const;
+    MEDLOADER_EXPORT void setMEDFileDS(MEDCoupling::MEDFileData* mfd);
+
+    MEDLOADER_EXPORT void write();
+
+private :
+
+    void getNodes( MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh0);
+    void getNSEG2(  MEDCoupling::mcIdType nbEdgesNSEG2, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh1);
+    void getNSEG3(  MEDCoupling::mcIdType nbEdgesNSEG2, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh1);
+    void getTRI3(  MEDCoupling::mcIdType nbTRI3, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2);
+    void getTRI6(  MEDCoupling::mcIdType nbTRI6, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2);
+    void getQUAD4(  MEDCoupling::mcIdType nbQUAD4, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2);
+    void getQUAD8(  MEDCoupling::mcIdType nbQUAD8, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2);
+    void getQUAD9(  MEDCoupling::mcIdType nbQUAD9, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2);
+    void getTETRA4(  MEDCoupling::mcIdType nbTETRA4, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3);
+    void getTETRA10(  MEDCoupling::mcIdType nbTETRA10, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3);
+    void getPYRA5(  MEDCoupling::mcIdType nbPYRA5, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3);
+    void getHEXA8(  MEDCoupling::mcIdType nbHEXA8, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3);
+    void getHEXA20(  MEDCoupling::mcIdType nbHEXA20, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3);
+    void getHEXA27(  MEDCoupling::mcIdType nbHEXA27, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3);
+    void getPENTA6(  MEDCoupling::mcIdType nbPENTA6, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3);
+    int getGmfSolKwd(const int nbComp, const int dim);
+    MeshFormat::Status setFieldOnNodes(MEDCoupling::MEDFileFieldMultiTS * f, int iteration, int order, size_t compInfoSize);
+    MeshFormat::Status setFieldOnCells(MEDCoupling::MEDFileFieldMultiTS * f, int iteration, int order, std::vector<int> levs );
+    void extractSymetricTensor(double fullTensor[], double*& symTensor);
+    void linkFamilyToNodes();
+    void linkFamilyToCells();
+    void writeCells();
+
+    bool checkFileName();
+    bool checkFieldFileName();
+    void forward_shift(std::vector<MEDCoupling::mcIdType> &conn);
+    MeshFormat::Status perform();
+    MeshFormat::Status performFields();
+    MeshFormat::Status addMessage(const std::string& msg, const bool isFatal = false);
+
+    std::string _meshFileName;
+    MeshFormat::MeshFormatParser _writer;
+    std::vector<std::string> _fieldFileNames;
+    MEDCoupling::MEDFileData* _mfd;
+    MEDCoupling::MCAuto< MEDCoupling::MEDFileMesh > _mesh;
+    std::vector< MEDCoupling::MCAuto< MEDCoupling::MEDFileFieldMultiTS > > _fields;
+    std::vector< std::string > _myErrorMessages;
+    MeshFormat::Status                     _myStatus;
+    int _myCurrentFileId, _dim, _version;
+    std::string _myCurrentOpenFile;
+    std::map<int, MeshFormatNode> _idNodeToNode;
+    std::map < INTERP_KERNEL::NormalizedCellType, std::map<int, MeshFormatCell> > _typeToIdCellToCell;
+
+};
+}
+#endif //MESHFORMATWRITER_HXX
index 741e4adeab3d3e7c5927878a378f3cf9cf458f41..b8d1011ef1092a91bbe99da1217cee1f591f4381 100644 (file)
@@ -42,6 +42,8 @@
 #include "MEDLoaderTypemaps.i"
 #include "SauvReader.hxx"
 #include "SauvWriter.hxx"
+#include "MeshFormatReader.hxx"
+#include "MeshFormatWriter.hxx"
 
 using namespace MEDCoupling;
 %}
@@ -309,6 +311,7 @@ using namespace MEDCoupling;
 %newobject MEDCoupling::SauvReader::New;
 %newobject MEDCoupling::SauvReader::loadInMEDFileDS;
 
+
 %newobject MEDCoupling::MEDFileMeshStruct::New;
 %newobject MEDCoupling::MEDMeshMultiLev::prepare;
 %newobject MEDCoupling::MEDMeshMultiLev::buildDataArray;
@@ -316,6 +319,10 @@ using namespace MEDCoupling;
 %newobject MEDCoupling::MEDFileFastCellSupportComparator::New;
 %newobject MEDCoupling::MEDFileFastCellSupportComparator::buildFromScratchDataSetSupport;
 
+%newobject MEDCoupling::MeshFormatReader::loadInMEDFileDS;
+%newobject MEDCoupling::MeshFormatReader::MeshFormatReader;
+%newobject MEDCoupling::MeshFormatWriter::MeshFormatWriter;
+
 %feature("unref") MEDFileMesh "$this->decrRef();"
 %feature("unref") MEDFileUMesh "$this->decrRef();"
 %feature("unref") MEDFileCMesh "$this->decrRef();"
@@ -4328,6 +4335,32 @@ namespace MEDCoupling
       }
     }
   };
+  
+  class MeshFormatReader
+  {
+  public:
+    MeshFormatReader(const std::string& meshFileName, const std::vector<std::string>& fieldFileName);
+    MeshFormatReader();
+    MEDFileData* loadInMedFileDS();
+    void setMeshName(const std::string& theMeshName);
+    std::string getMeshName() const;
+    void setFile(const std::string& theFileName);
+    void setFieldFileNames(const std::vector<std::string>& theFieldFileNames);
+    std::vector<std::string> getFieldFileNames() const;
+  };
+  class MeshFormatWriter
+  {
+  public:
+    MeshFormatWriter(const std::string& meshFileName, const std::vector<std::string>& fieldFileNames);
+    MeshFormatWriter();
+    void setMeshFileName(const std::string& meshFileName);
+    std::string getMeshFileName() const;
+    void setFieldFileNames(const std::vector<std::string>& fieldFileNames);
+    std::vector<std::string> getFieldFileNames() const;
+    void setMEDFileDS(MEDCoupling::MEDFileData* mfd);
+    void write();
+  };
+  
 }
 
 %pythoncode %{
diff --git a/src/MEDLoader/libmesh5.cxx b/src/MEDLoader/libmesh5.cxx
new file mode 100644 (file)
index 0000000..15f8a1d
--- /dev/null
@@ -0,0 +1,1380 @@
+// Copyright (C) 2021  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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
+//
+
+/*----------------------------------------------------------*/
+/*                                                                                                                      */
+/*                                              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.hxx"
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+using namespace MeshFormat;
+
+
+
+/*----------------------------------------------------------*/
+/* Global variables                                                                                     */
+/*----------------------------------------------------------*/
+
+// see MeshGems/Docs/meshgems_formats_description.pdf
+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"},
+    {"Fault_MultipleEdge", "Fault_MultipleEdge", "i", "i"}
+};
+
+
+
+MeshFormatParser::MeshFormatParser():GmfIniFlg(0)
+{
+
+}
+
+/*----------------------------------------------------------*/
+/* Open a mesh file in read or write mod                                        */
+/*----------------------------------------------------------*/
+
+int MeshFormatParser::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 defined(WIN32) && defined(UNICODE)
+    wchar_t* encoded = 0;
+    int size_needed = 0;
+#endif
+    if(!GmfIniFlg)
+    {
+        for(i=0; i<=MaxMsh; i++)
+            //~GmfMshTab[i] = NULL;
+            GmfMshTab[i] = nullptr;
+
+        GmfIniFlg = 1;
+    }
+
+    /*---------------------*/
+    /* MESH STRUCTURE INIT */
+    /*---------------------*/
+
+    for(i=1; i<=MaxMsh; i++)
+        if(!GmfMshTab[i])
+        {
+            MshIdx = i;
+            break;
+        }
+
+
+    if( !MshIdx || !(msh = new GmfMshSct() ) )
+        return(0);
+
+    /* Copy the FilNam into the structure */
+
+    if(strlen(FilNam) + 7 >= GmfStrSiz)
+    {
+        //~free (msh);
+        delete 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 = static_cast<int>(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);
+        delete msh;
+        return(0);
+    }
+
+    /* Open the file in the required mod and initialise 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 defined(WIN32) && defined(UNICODE)
+        size_needed = MultiByteToWideChar(CP_UTF8, 0, msh->FilNam, strlen(msh->FilNam), NULL, 0);
+        //~encoded = malloc((size_needed + 1)*sizeof(wchar_t));
+        encoded = new wchar_t[size_needed + 1] ;
+        MultiByteToWideChar(CP_UTF8, 0, msh->FilNam, strlen(msh->FilNam), encoded, size_needed);
+        encoded[size_needed] = '\0';
+        if (!(msh->hdl = _wfopen(encoded, L"rb")))
+#else
+        if (!(msh->hdl = fopen(msh->FilNam, "rb")))
+#endif
+        {
+
+            delete msh;
+#if defined(WIN32) && defined(UNICODE)
+
+            delete [] encoded;
+#endif
+            return(0);
+        }
+
+#if defined(WIN32) && defined(UNICODE)
+
+        delete [] encoded;
+#endif
+
+        /* 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) )
+            {
+
+                delete msh;
+                return(0);
+            }
+
+            ScaWrd(msh, (unsigned char *)&msh->ver);
+
+            if( (msh->ver < 1) || (msh->ver > 3) )
+            {
+
+                delete msh;
+                return(0);
+            }
+
+            if( (msh->ver == 3) && (sizeof(long) == 4) )
+            {
+
+                delete msh;
+                return(0);
+            }
+
+            ScaWrd(msh, (unsigned char *)&KwdCod);
+
+            if(KwdCod != GmfDimension)
+            {
+
+                delete 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)
+            {
+
+                delete msh;
+                return(0);
+            }
+
+            fscanf(msh->hdl, "%d", &msh->ver);
+
+            if( (msh->ver < 1) || (msh->ver > 3) )
+            {
+
+                delete msh;
+                return(0);
+            }
+
+            do
+            {
+                res = fscanf(msh->hdl, "%s", str);
+            } while( (res != EOF) && strcmp(str, "Dimension") );
+
+            if(res == EOF)
+            {
+
+                delete msh;
+                return(0);
+            }
+
+            fscanf(msh->hdl, "%d", &msh->dim);
+        }
+
+        if( (msh->dim != 2) && (msh->dim != 3) )
+        {
+
+            delete msh;
+            return(0);
+        }
+
+        (*PtrVer) = msh->ver;
+        (*PtrDim) = msh->dim;
+
+        /*------------*/
+        /* KW READING */
+        /*------------*/
+
+        /* Read the list of kw present in the file */
+
+        if(!ScaKwdTab(msh))
+        {
+
+            delete 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) )
+        {
+
+            delete msh;
+            return(0);
+        }
+
+        if( (msh->ver == 3) && (sizeof(long) == 4) )
+        {
+
+            delete msh;
+            return(0);
+        }
+
+        if( (msh->dim != 2) && (msh->dim != 3) )
+        {
+
+            delete msh;
+            return(0);
+        }
+
+        /* Create the mesh file */
+#if defined(WIN32) && defined(UNICODE)
+        size_needed = MultiByteToWideChar(CP_UTF8, 0, msh->FilNam, strlen(msh->FilNam), NULL, 0);
+
+        encoded = new wchar_t[size_needed + 1];
+        MultiByteToWideChar(CP_UTF8, 0, msh->FilNam, strlen(msh->FilNam), encoded, size_needed);
+        encoded[size_needed] = '\0';
+        if (!(msh->hdl = _wfopen(encoded, L"wb")))
+#else
+        if(!(msh->hdl = fopen(msh->FilNam, "wb")))
+#endif
+        {
+
+            delete msh;
+#if defined(WIN32) && defined(UNICODE)
+
+            delete []encoded;
+#endif
+            return(0);
+        }
+
+#if defined(WIN32) && defined(UNICODE)
+
+        delete []encoded;
+#endif
+        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
+    {
+
+        delete msh;
+        return(0);
+    }
+}
+
+
+/*----------------------------------------------------------*/
+/* Close a meshfile in the right way                                            */
+/*----------------------------------------------------------*/
+
+int MeshFormatParser::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;
+
+
+    delete msh;
+
+    GmfMshTab[ MshIdx ] = nullptr;
+
+    return(res);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read the number of lines and set the position to this kwd*/
+/*----------------------------------------------------------*/
+
+int MeshFormatParser::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 MeshFormatParser::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 MeshFormatParser::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 > static_cast<long>(2E9))
+        return(0);
+    else
+        return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a full line from the current kwd                                        */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::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 MeshFormatParser::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] = static_cast<float>(va_arg(VarArg, double));
+                    else if(kwd->fmt[i] == 'n') {
+                        nb_repeat = va_arg(VarArg, int);
+                        msh->FltBuf[i] = static_cast<float> (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 MeshFormatParser::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                                          */
+/*----------------------------------------------------------*/
+
+int MeshFormatParser::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 current position in file (just before the data) */
+                // printf("libmesh ScaKwdTab %s\n", str);
+                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                                          */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::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        */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::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 < static_cast<int>(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                                      */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::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                            */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::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                      */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::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                            */
+/*----------------------------------------------------------*/
+
+long MeshFormatParser::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                                       */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::RecWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+    fwrite(wrd, WrdSiz, 1, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write an eight bytes word to a mesh file                                     */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::RecDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+    fwrite(wrd, WrdSiz, 2, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a block of four bytes word to a mesh file                      */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::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                         */
+/*----------------------------------------------------------*/
+
+void MeshFormatParser::SetPos(GmfMshSct *msh, long pos)
+{
+    int IntVal;
+
+    if(msh->ver >= 3)
+        RecDblWrd(msh, (unsigned char*)&pos);
+    else
+    {
+        IntVal = static_cast<int>(pos);
+        RecWrd(msh, (unsigned char*)&IntVal);
+    }
+}
diff --git a/src/MEDLoader/libmesh5.hxx b/src/MEDLoader/libmesh5.hxx
new file mode 100644 (file)
index 0000000..efb1552
--- /dev/null
@@ -0,0 +1,236 @@
+// Copyright (C) 2021  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// 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
+//
+
+#ifndef MESHFORMATPARSER_HXX
+#define MESHFORMATPARSER_HXX
+/*----------------------------------------------------------*/
+/*                                                                                                                      */
+/*                                              LIBMESH V 5.46                                          */
+/*                                                                                                                      */
+/*----------------------------------------------------------*/
+/*                                                                                                                      */
+/*      Description:            handle .meshb file format I/O           */
+/*      Author:                         Loic MARECHAL                                           */
+/*      Creation date:          feb 16 2007                                                     */
+/*      Last modification:      dec 12 2020                                                     */
+/*                                                                                                                      */
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Defines                                                                                                      */
+/*----------------------------------------------------------*/
+
+
+#define GmfStrSiz 1024
+#define GmfMaxTyp 1000
+#define GmfMaxKwd 81
+#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
+
+
+/*----------------------------------------------------------*/
+/* 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
+
+
+// see MeshGems/Docs/meshgems_formats_description.pdf
+extern const char* GmfKwdFmt[ GmfMaxKwd + 1 ][4];
+/*----------------------------------------------------------*/
+/* Structures                                                                                           */
+/*----------------------------------------------------------*/
+namespace  MeshFormat {
+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;
+
+
+
+
+
+// see MeshGems/Docs/meshgems_formats_description.pdf
+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, \
+    GmfFault_MultipleEdge
+};
+
+
+
+class MeshFormatParser {
+    /*----------------------------------------------------------*/
+    /* External procedures                                                                          */
+    /*----------------------------------------------------------*/
+public :
+    MeshFormatParser();
+    int GmfOpenMesh(const char *, int, ...);
+    int GmfCloseMesh(int);
+    int GmfStatKwd(int, int, ...);
+    int GmfGotoKwd(int, int);
+    int GmfSetKwd(int, int, ...);
+    void GmfGetLin(int, int, ...);
+    void GmfSetLin(int, int, ...);
+private :
+
+
+    /*----------------------------------------------------------*/
+    /*  private procedures methods                                                       */
+    /*----------------------------------------------------------*/
+
+    void ScaWrd(GmfMshSct *, unsigned char *);
+    void ScaDblWrd(GmfMshSct *, unsigned char *);
+    void ScaBlk(GmfMshSct *, unsigned char *, int);
+    long GetPos(GmfMshSct *);
+    void RecWrd(GmfMshSct *, unsigned char *);
+    void RecDblWrd(GmfMshSct *, unsigned char *);
+    void RecBlk(GmfMshSct *, unsigned char *, int);
+    void SetPos(GmfMshSct *, long);
+    int ScaKwdTab(GmfMshSct *);
+    void ExpFmt(GmfMshSct *, int);
+    void ScaKwdHdr(GmfMshSct *, int);
+
+    void GmfCpyLin(int, int, int);
+
+
+    int GmfIniFlg;
+    GmfMshSct *GmfMshTab[ MaxMsh + 1 ];
+
+
+
+
+
+};
+
+}
+#endif // MESHFORMATPARSER_HXX