From 47fc37875313e4407e27ca91461c81ee82072095 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Thu, 18 Feb 2021 10:28:12 +0100 Subject: [PATCH] CS work : MeshGems reader/writer --- src/MEDLoader/CMakeLists.txt | 4 + src/MEDLoader/MEDMESHConverterUtilities.cxx | 58 + src/MEDLoader/MEDMESHConverterUtilities.hxx | 123 ++ src/MEDLoader/MeshFormatReader.cxx | 1000 ++++++++++++++ src/MEDLoader/MeshFormatReader.hxx | 220 +++ src/MEDLoader/MeshFormatWriter.cxx | 1137 +++++++++++++++ src/MEDLoader/MeshFormatWriter.hxx | 134 ++ src/MEDLoader/Swig/MEDLoaderCommon.i | 33 + src/MEDLoader/libmesh5.cxx | 1380 +++++++++++++++++++ src/MEDLoader/libmesh5.hxx | 236 ++++ 10 files changed, 4325 insertions(+) create mode 100644 src/MEDLoader/MEDMESHConverterUtilities.cxx create mode 100644 src/MEDLoader/MEDMESHConverterUtilities.hxx create mode 100644 src/MEDLoader/MeshFormatReader.cxx create mode 100644 src/MEDLoader/MeshFormatReader.hxx create mode 100644 src/MEDLoader/MeshFormatWriter.cxx create mode 100644 src/MEDLoader/MeshFormatWriter.hxx create mode 100644 src/MEDLoader/libmesh5.cxx create mode 100644 src/MEDLoader/libmesh5.hxx diff --git a/src/MEDLoader/CMakeLists.txt b/src/MEDLoader/CMakeLists.txt index 3f659f7b2..8c54e4ab2 100644 --- a/src/MEDLoader/CMakeLists.txt +++ b/src/MEDLoader/CMakeLists.txt @@ -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 index 000000000..d58fa1cec --- /dev/null +++ b/src/MEDLoader/MEDMESHConverterUtilities.cxx @@ -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 index 000000000..022eb034a --- /dev/null +++ b/src/MEDLoader/MEDMESHConverterUtilities.hxx @@ -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 +# include +#include +# include +#include + + + +#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 + Comment( const T &anything ) { + _s << anything ; + this->std::string::operator=( _s.str() ); + } + + template + 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 +void FreeVector(TVECTOR& vec) +{ + TVECTOR v2; + vec.swap( v2 ); +} +template +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 index 000000000..7f405bbc1 --- /dev/null +++ b/src/MEDLoader/MeshFormatReader.cxx @@ -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 +#include + +namespace MEDCoupling { +MeshFormatReader::MeshFormatReader():_myMeshName("MESH") +{} +MeshFormatReader::MeshFormatReader(const std::string& meshFileName, + const std::vector& fieldFileName):_myFile(meshFileName), + _myFieldFileNames(fieldFileName), + _myCurrentFileId(0), + _myMeshName("MESH") +{} + +MeshFormatReader::~MeshFormatReader() +{} + +MEDCoupling::MCAuto 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::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 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 timeStamp; + MEDCoupling::MCAuto tsField = MEDCoupling::MEDFileFieldMultiTS::New(); + MEDCoupling::MCAuto 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& theFieldFileNames) +{ + _myFieldFileNames = theFieldFileNames; +} +std::vector 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; ialloc( nbNodes, _dim ); + double* coordPrt = coordArray->getPointer(); + std::vector 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 (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 (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 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 (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 (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 > 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& 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& 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 (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 (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 > 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& 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& 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 (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 (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 (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 > 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& 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& 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 (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 (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 (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 > 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& 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& 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 (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 (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 (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 (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 levs = _uMesh->getNonEmptyLevels(); + for (size_t iDim = 0; iDim* > famDim = _fams.getMapAtLevel(dimRelMax); + std::map * >::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 * cellsInFam = _meshFormatFamsIt->second; + if (!famId) continue; + std::vector ::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 levs = _uMesh->getNonEmptyLevels(); + int dimRelMax = 1; + std::map * > famDim = _fams.getMapAtLevel(dimRelMax); + std::map * >::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* > famDimAtLevel = _fams.getMapAtLevel(dimMesh); + std::map * >::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 * cellsInFam = _meshFormatFamsIt->second; + std::vector ::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 index 000000000..15e383653 --- /dev/null +++ b/src/MEDLoader/MeshFormatReader.hxx @@ -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 +#include +#include +#include +#include +#include +#include "MCAuto.hxx" +#include "InterpKernelException.hxx" +#include "NormalizedUnstructuredMesh.hxx" +#include "MCType.hxx" +#include "MEDMESHConverterUtilities.hxx" +#include "libmesh5.hxx" + +#include +#include +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 * > _meshFormatFams; + std::map * > _meshFormatFams_0; + std::map * > _meshFormatFams_1; + std::map * > _meshFormatFams_2; + std::map * > _meshFormatFamsNodes; + +public: + void insert(std::pair addToFamily, int dimRelMax) + { + insertPairInMap(_meshFormatFams, addToFamily); + insertPairInMap(getMapAtLevel(dimRelMax), addToFamily); + } +private: + void insertPairInMap(std::map * >& aMap, std::pair addToFamily) + { + std::map * >::iterator it = aMap.find(addToFamily.first); + if (it!= aMap.end()) + { + aMap[addToFamily.first]->push_back(addToFamily.second); + } + else + { + std::vector * tmpVec = new std::vector ; + tmpVec->push_back(addToFamily.second); + aMap.insert(std::pair * > (addToFamily.first, tmpVec) ); + + } + + } +public: + void remove(std::pair removeFromFamily, int dimRelMax) + { + removePairFromMap(_meshFormatFams, removeFromFamily); + removePairFromMap(getMapAtLevel(dimRelMax), removeFromFamily); + + } +private: + void removePairFromMap(std::map * > & aMap, const std::pair removeFromFamily) + { + + if (!aMap.size() ) return; + std::map * >::iterator itTmp = aMap.find(removeFromFamily.first); + if (itTmp == aMap.end()) return; + else + { + std::vector * tmpVec2 = aMap[removeFromFamily.first]; +#if __GNUC_PREREQ(4,9) + std::vector ::const_iterator itt2; +#else + std::vector ::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 * > & 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 * > & aMap) + { + std::map * >::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& fieldFileName); + MEDLOADER_EXPORT ~MeshFormatReader(); + + MEDLOADER_EXPORT MEDCoupling::MCAuto 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& theFieldFileNames); + MEDLOADER_EXPORT std::vector 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 _myFieldFileNames; + int _dim, _version; + std::vector< std::string > _myErrorMessages; + MeshFormat::Status _myStatus; + MEDCoupling::MCAuto _myMed; + MEDCoupling::MCAuto _uMesh; + MEDCoupling::MCAuto _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 index 000000000..346e4e106 --- /dev/null +++ b/src/MEDLoader/MeshFormatWriter.cxx @@ -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 +#include +#include +#include +#include + + +namespace MEDCoupling { + +MeshFormatWriter::MeshFormatWriter() +{} +MeshFormatWriter::MeshFormatWriter(const std::string& meshFileName, + const std::vector& fieldFileNames):_meshFileName(meshFileName), + _fieldFileNames(fieldFileNames) +{} +MeshFormatWriter::~MeshFormatWriter() +{} +void MeshFormatWriter::setMeshFileName(const std::string& meshFileName) +{ + _meshFileName = meshFileName; +} +void MeshFormatWriter::setFieldFileNames(const std::vector& 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; igetNumberOfFields(); i++ ) + { + MEDCoupling::MEDFileAnyTypeFieldMultiTS* field = fields->getFieldAtPos(i); + MEDCoupling::MEDFileFieldMultiTS * f = dynamic_cast(field); + _fields.push_back(f); + } + + +} + +void MeshFormatWriter::write() +{ + + MeshFormat::Localizer loc; + + MEDCoupling::MCAuto 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 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::const_iterator fieldFileIt = _fieldFileNames.begin(); + int iField = 0; + std::vector 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 > fTypes = f->getTypesOfFieldAvailable(); + std::vector< std::pair > iters = f->getIterations(); + const std::vector& compInfo = f->getInfo(); + std::pair 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 types; + std::vector< std::vector > typesF; + std::vector< std::vector > pfls, locs; + std::vector< std::vector< std::pair > > 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 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; kfield( 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 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 &conn) +{ + std::vector::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 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 (idNode, e)); + + coordPrt+= _dim; + j--; + idNode++; + } + linkFamilyToNodes(); + std::map ::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 elementId = umesh1->giveCellsWithType(INTERP_KERNEL::NORM_SEG2); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh1->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + + MeshFormatCell e(INTERP_KERNEL::NORM_SEG2, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_SEG2, idCellToCell) ); +} + + +void MeshFormatWriter::getNSEG3( MEDCoupling::mcIdType nbEdgesNSEG3, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh1) +{ + + + MEDCoupling::MCAuto elementId = umesh1->giveCellsWithType(INTERP_KERNEL::NORM_SEG3); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + + std::vector conn; + umesh1->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_SEG3, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_SEG3, idCellToCell) ); +} + + +void MeshFormatWriter::getTRI3( MEDCoupling::mcIdType nbTRI3, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2) +{ + + MEDCoupling::MCAuto elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_TRI3); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh2->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_TRI3, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_TRI3, idCellToCell) ); +} + + +void MeshFormatWriter::getTRI6( MEDCoupling::mcIdType nbTRI6, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2) +{ + + MEDCoupling::MCAuto elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_TRI6); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh2->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_TRI6, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_TRI6, idCellToCell) ); +} + +void MeshFormatWriter::getQUAD4( MEDCoupling::mcIdType nbQUAD4, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2) +{ + + MEDCoupling::MCAuto elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_QUAD4); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh2->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_QUAD4, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_QUAD4, idCellToCell) ); +} + +void MeshFormatWriter::getQUAD8(MEDCoupling::mcIdType nbQUAD8, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2) +{ + + MEDCoupling::MCAuto elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_QUAD8); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh2->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_QUAD8, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_QUAD8, idCellToCell) ); +} + +void MeshFormatWriter::getQUAD9(MEDCoupling::mcIdType nbQUAD9, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh2) +{ + + MEDCoupling::MCAuto elementId = umesh2->giveCellsWithType(INTERP_KERNEL::NORM_QUAD9); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh2->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_QUAD9, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_QUAD9, idCellToCell) ); +} + +void MeshFormatWriter::getTETRA4(MEDCoupling::mcIdType nbTETRA4, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3) +{ + + MEDCoupling::MCAuto elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_TETRA4); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh3->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_TETRA4, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_TETRA4, idCellToCell) ); +} + +void MeshFormatWriter::getTETRA10(MEDCoupling::mcIdType nbTETRA10, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3) +{ + + MEDCoupling::MCAuto elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_TETRA10); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh3->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_TETRA10, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_TETRA10, idCellToCell) ); +} + +void MeshFormatWriter::getPYRA5(MEDCoupling::mcIdType nbPYRA5, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3) +{ + + MEDCoupling::MCAuto elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_PYRA5); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh3->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_PYRA5, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_PYRA5, idCellToCell) ); +} + +void MeshFormatWriter::getHEXA8(MEDCoupling::mcIdType nbHEXA8, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3) +{ + + MEDCoupling::MCAuto elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_HEXA8); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh3->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_HEXA8, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_HEXA8, idCellToCell) ); +} +void MeshFormatWriter::getHEXA20(MEDCoupling::mcIdType nbHEXA20, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3) +{ + + MEDCoupling::MCAuto elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_HEXA20); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh3->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_HEXA20, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_HEXA20, idCellToCell) ); +} +void MeshFormatWriter::getHEXA27(MEDCoupling::mcIdType nbHEXA27, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3) +{ + + MEDCoupling::MCAuto elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_HEXA27); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh3->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_HEXA27, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_HEXA27, idCellToCell) ); +} + +void MeshFormatWriter::getPENTA6(MEDCoupling::mcIdType nbPENTA6, MEDCoupling::MCAuto< MEDCoupling::MEDCouplingUMesh > umesh3) +{ + + MEDCoupling::MCAuto elementId = umesh3->giveCellsWithType(INTERP_KERNEL::NORM_PENTA6); + std::map idCellToCell; + for ( const mcIdType *it=elementId->begin(); it!=elementId->end(); it++ ) + { + std::vector conn; + umesh3->getNodeIdsOfCell(*it, conn) ; + forward_shift(conn); + MeshFormatCell e(INTERP_KERNEL::NORM_PENTA6, (int)*it); + e.setConn(conn); + idCellToCell.insert(std::pair (*it, e)); + } + _typeToIdCellToCell.insert(std::pair >(INTERP_KERNEL::NORM_PENTA6, idCellToCell) ); +} + + +void MeshFormatWriter::linkFamilyToNodes() +{ + + std::map famInfos = _mesh->getFamilyInfo(); + std::map::const_iterator famIt = famInfos.begin(); + for (; famIt != famInfos.end(); ++famIt) + { + if(!famIt->second) continue; //FAMILLE_ZERO + MEDCoupling::MCAuto nodeIds = _mesh->getNodeFamilyArr(famIt->first); + const MEDCoupling::mcIdType * nodeIdsIt = nodeIds->begin(), * famIDEnd = nodeIds->end(); + for(; nodeIdsIt< famIDEnd; ++nodeIdsIt) { + + std::map ::iterator itNode = _idNodeToNode.find((int)*nodeIdsIt); + if (itNode == _idNodeToNode.end()) continue; + else itNode->second._famId =(int) famIt->second; + + + } + } +} + + + +void MeshFormatWriter::linkFamilyToCells() +{ + + std::vector 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 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 >::iterator itCellMap = _typeToIdCellToCell.find(type); + if (itCellMap == _typeToIdCellToCell.end()) continue; + else + { + std::map ::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 >::iterator typeCellMapIt = _typeToIdCellToCell.begin(); + for (; typeCellMapIt!= _typeToIdCellToCell.end(); ++typeCellMapIt) + { + std::map::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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 index 000000000..6b609d6b1 --- /dev/null +++ b/src/MEDLoader/MeshFormatWriter.hxx @@ -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 +#include +#include +#include "MCAuto.hxx" +#include "InterpKernelException.hxx" +#include "NormalizedUnstructuredMesh.hxx" +#include "MCType.hxx" +#include "MEDMESHConverterUtilities.hxx" +#include "libmesh5.hxx" + +#include "MEDFileMesh.hxx" +#include + +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 cpy) + { + conn.clear(); + std::copy(cpy.begin(), cpy.end(), std::back_inserter(conn)); + } + std::vector conn; +}; + + +class MeshFormatWriter +{ +public : + MEDLOADER_EXPORT MeshFormatWriter(); + MEDLOADER_EXPORT MeshFormatWriter(const std::string& meshFileName, const std::vector& 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& fieldFileNames); + MEDLOADER_EXPORT std::vector 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 levs ); + void extractSymetricTensor(double fullTensor[], double*& symTensor); + void linkFamilyToNodes(); + void linkFamilyToCells(); + void writeCells(); + + bool checkFileName(); + bool checkFieldFileName(); + void forward_shift(std::vector &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 _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 _idNodeToNode; + std::map < INTERP_KERNEL::NormalizedCellType, std::map > _typeToIdCellToCell; + +}; +} +#endif //MESHFORMATWRITER_HXX diff --git a/src/MEDLoader/Swig/MEDLoaderCommon.i b/src/MEDLoader/Swig/MEDLoaderCommon.i index 741e4adea..b8d1011ef 100644 --- a/src/MEDLoader/Swig/MEDLoaderCommon.i +++ b/src/MEDLoader/Swig/MEDLoaderCommon.i @@ -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& 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& theFieldFileNames); + std::vector getFieldFileNames() const; + }; + class MeshFormatWriter + { + public: + MeshFormatWriter(const std::string& meshFileName, const std::vector& fieldFileNames); + MeshFormatWriter(); + void setMeshFileName(const std::string& meshFileName); + std::string getMeshFileName() const; + void setFieldFileNames(const std::vector& fieldFileNames); + std::vector 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 index 000000000..15f8a1ddd --- /dev/null +++ b/src/MEDLoader/libmesh5.cxx @@ -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 +#include +#include +#include +#include +#include +#include +#include "libmesh5.hxx" +#ifdef WIN32 +#include +#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(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; iNmbTyp; 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; iNmbTyp; 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; iNmbTyp; 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; iNmbTyp; 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(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; iSolSiz; 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; khdl, "%d", va_arg(VarArg, int *)); + } + else + fscanf(msh->hdl, "%d", va_arg(VarArg, int *)); + } + else + { + for(i=0; iSolSiz; 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; ktyp & Asc) + { + for(i=0; iSolSiz; 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; khdl, "%d", va_arg(VarArg, int *)); + } + else + fscanf(msh->hdl, "%d", va_arg(VarArg, int *)); + } + else + for(i=0; iSolSiz; 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; kver == 1) + { + FltSolTab = va_arg(VarArg, float *); + + if(msh->typ & Asc) + for(j=0; jSolSiz; 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; jSolSiz; j++) + fscanf(msh->hdl, "%lf", &DblSolTab[j]); + else + for(j=0; jSolSiz; 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; iSolSiz; 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; khdl, "%d ", va_arg(VarArg, int)); + } + else + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + } + else + { + int size_of_block = kwd->SolSiz; + for(i=0; iSolSiz; i++) + if(kwd->fmt[i] == 'r') + msh->FltBuf[i] = static_cast(va_arg(VarArg, double)); + else if(kwd->fmt[i] == 'n') { + nb_repeat = va_arg(VarArg, int); + msh->FltBuf[i] = static_cast (nb_repeat); + for(k=0; kIntBuf[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; iSolSiz; 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; khdl, "%d ", va_arg(VarArg, int)); + } + else + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + } + else + { + pos = 0; + + for(i=0; iSolSiz; 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; kbuf[ 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; jSolSiz; 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; jSolSiz; 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; iSolSiz; 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; ktyp & 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; iNmbTyp; i++) + fscanf(msh->hdl, "%d", &kwd->TypTab[i]); + } + else + { + ScaWrd(msh, (unsigned char *)&kwd->NmbTyp); + + for(i=0; iNmbTyp; 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; iNmbTyp; 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(strlen(InpFmt)) ) + { + chr = InpFmt[ i++ ]; + + if(chr == 'd') + { + chr = InpFmt[i++]; + + for(j=0; jdim; j++) + kwd->fmt[ kwd->SolSiz++ ] = chr; + } + else if(chr == 's') + { + chr = InpFmt[i++]; + + for(j=0; jfmt[ kwd->SolSiz++ ] = chr; + } + else + kwd->fmt[ kwd->SolSiz++ ] = chr; + } + + for(i=0; iSolSiz; 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; iver >= 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(pos); + RecWrd(msh, (unsigned char*)&IntVal); + } +} diff --git a/src/MEDLoader/libmesh5.hxx b/src/MEDLoader/libmesh5.hxx new file mode 100644 index 000000000..efb1552ce --- /dev/null +++ b/src/MEDLoader/libmesh5.hxx @@ -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 -- 2.39.2