From: eap Date: Wed, 10 Aug 2011 10:10:26 +0000 (+0000) Subject: 0020511: EDF 1101 SMESH : Add CGNS to Mesh Format Supported X-Git-Tag: V6_4_0a1~132 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=75bac8d6f5e2acd561b16b295e68cb07f7040cb9;p=modules%2Fsmesh.git 0020511: EDF 1101 SMESH : Add CGNS to Mesh Format Supported --- diff --git a/doc/salome/gui/SMESH/input/importing_exporting_meshes.doc b/doc/salome/gui/SMESH/input/importing_exporting_meshes.doc index cdedf8d33..52ff261e3 100644 --- a/doc/salome/gui/SMESH/input/importing_exporting_meshes.doc +++ b/doc/salome/gui/SMESH/input/importing_exporting_meshes.doc @@ -3,15 +3,15 @@ \page importing_exporting_meshes_page Importing and exporting meshes \n In MESH there is a functionality allowing importation/exportation -of meshes from/to \b MED, \b UNV (I-DEAS 10), \b DAT (Nastran) and STL -format files. You can also export a group as a whole mesh. +of meshes from/to \b MED, \b UNV (I-DEAS 10), \b DAT (Nastran), \b STL +and \b CGNS format files. You can also export a group as a whole mesh. To import a mesh:
  1. From the \b File menu choose the \b Import item, from its sub-menu -select the corresponding format (MED, UNV and DAT) of the file containing +select the corresponding format (MED, UNV, DAT, STL and CGNS) of the file containing your mesh.
  2. In the standard Search File dialog box find the file for importation. It is possible to select multiple files to be imported all at once.
  3. @@ -26,8 +26,8 @@ importation. It is possible to select multiple files to be imported all at once.
    1. Select the object you wish to export.
    2. From the \b File menu choose the \b Export item, from its sub-menu -select the format (MED, UNV, DAT and STL) of the file which will contain your -exported mesh.
    3. +select the format (MED, UNV, DAT, STL and CGNS) of the file which will +contain your exported mesh.
    4. In the standard Search File select a location for the exported file and enter its name.
    5. Click the \b OK button.
    6. diff --git a/doc/salome/gui/SMESH/input/index.doc b/doc/salome/gui/SMESH/input/index.doc index 2522b5bcb..776dbeafe 100644 --- a/doc/salome/gui/SMESH/input/index.doc +++ b/doc/salome/gui/SMESH/input/index.doc @@ -6,7 +6,7 @@ \n \b MESH module of SALOME is destined for:
        -
      • \ref importing_exporting_meshes_page "import and export of meshes in MED format";
      • +
      • \ref importing_exporting_meshes_page "import and export of meshes in different formats";
      • \subpage about_meshes_page "meshing geometrical models" previously created or imported by the Geometry component;
      • \subpage viewing_meshes_overview_page "viewing created meshes" in diff --git a/src/DriverCGNS/DriverCGNS_Read.cxx b/src/DriverCGNS/DriverCGNS_Read.cxx new file mode 100644 index 000000000..f051d5508 --- /dev/null +++ b/src/DriverCGNS/DriverCGNS_Read.cxx @@ -0,0 +1,1184 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : DriverCGNS_Read.cxx +// Created : Thu Jun 30 10:33:31 2011 +// Author : Edward AGAPOV (eap) + +#include "DriverCGNS_Read.hxx" + +#include "SMDS_MeshNode.hxx" +#include "SMESHDS_Group.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESH_Comment.hxx" + +#include + +#include + +#include + +#if CGNS_VERSION < 3100 +# define cgsize_t int +#endif + +#define NB_ZONE_SIZE_VAL 9 +#define CGNS_NAME_SIZE 33 +#define CGNS_STRUCT_RANGE_SZ 6 + +using namespace std; + +namespace +{ + //================================================================================ + /*! + * \brief Data of a zone + */ + struct TZoneData + { + int _id; + int _nodeIdShift; // nb nodes in previously read zones + int _elemIdShift; // nb faces in previously read zones + int _nbNodes, _nbElems; + int _meshDim; + int _sizeX, _sizeY, _sizeZ, _nbCells; // structured + cgsize_t _sizes[NB_ZONE_SIZE_VAL]; + CGNS_ENUMT(ZoneType_t) _type; + map< int, int > _nodeReplacementMap;/* key: id of node to replace (in this zone), + value: id of node to replace by (in another zone) + id values include _nodeIdShift of the zones */ + void SetSizeAndDim( cgsize_t* sizes, int meshDim ) + { + _meshDim = meshDim; + memcpy( _sizes, sizes, NB_ZONE_SIZE_VAL*sizeof(cgsize_t)); + _sizeX = _sizes[0]; + _sizeY = _meshDim > 1 ? _sizes[1] : 0; + _sizeZ = _meshDim > 2 ? _sizes[2] : 0; + _nbCells = (_sizeX - 1) * ( _meshDim > 1 ? _sizeY : 1 ) * ( _meshDim > 2 ? _sizeZ : 1 ); + } + bool IsStructured() const { return ( _type == CGNS_ENUMV( Structured )); } + int IndexSize() const { return IsStructured() ? _meshDim : 1; } + string ReadZonesConnection(int file, int base, const map< string, TZoneData >& zonesByName); + void ReplaceNodes( int* ids, int nbIds, int idShift = 0 ) const; + + // Methods for a structured zone + + int NodeID( int i, int j, int k = 1 ) const + { + return _nodeIdShift + (k-1)*_sizeX*_sizeY + (j-1)*_sizeX + i; + } + int NodeID( const gp_XYZ& ijk ) const + { + return NodeID( int(ijk.X()), int(ijk.Y()), int(ijk.Z())); + } + void CellNodes( int i, int j, int k, cgsize_t* ids ) const + { + ids[0] = NodeID( i , j , k ); + ids[1] = NodeID( i , j+1, k ); + ids[2] = NodeID( i+1, j+1, k ); + ids[3] = NodeID( i+1, j , k ); + ids[4] = NodeID( i , j , k+1); + ids[5] = NodeID( i , j+1, k+1); + ids[6] = NodeID( i+1, j+1, k+1); + ids[7] = NodeID( i+1, j , k+1); + } + void CellNodes( int i, int j, cgsize_t* ids ) const + { + ids[0] = NodeID( i , j ); + ids[1] = NodeID( i , j+1 ); + ids[2] = NodeID( i+1, j+1 ); + ids[3] = NodeID( i+1, j ); + } + void IFaceNodes( int i, int j, int k, cgsize_t* ids ) const // face perpendiculaire to X (3D) + { + ids[0] = NodeID( i, j, k ); + ids[1] = ids[0] + _sizeX*( i==_sizeX ? 1 : _sizeY ); + ids[2] = ids[0] + _sizeX*( _sizeY + 1 ); + ids[3] = ids[0] + _sizeX*( i==_sizeX ? _sizeY : 1 ); + } + void JFaceNodes( int i, int j, int k, cgsize_t* ids ) const + { + ids[0] = NodeID( i, j, k ); + ids[1] = ids[0] + ( j==_sizeY ? _sizeX*_sizeY : 1); + ids[2] = ids[0] + _sizeX*_sizeY + 1; + ids[3] = ids[0] + ( j==_sizeY ? 1 : _sizeX*_sizeY); + } + void KFaceNodes( int i, int j, int k, cgsize_t* ids ) const + { + ids[0] = NodeID( i, j, k ); + ids[1] = ids[0] + ( k==_sizeZ ? 1 : _sizeX); + ids[2] = ids[0] + _sizeX + 1; + ids[3] = ids[0] + ( k==_sizeZ ? _sizeX : 1); + } + void IEdgeNodes( int i, int j, int k, cgsize_t* ids ) const // edge perpendiculaire to X (2D) + { + ids[0] = NodeID( i, j, 0 ); + ids[1] = ids[0] + _sizeX; + } + void JEdgeNodes( int i, int j, int k, cgsize_t* ids ) const + { + ids[0] = NodeID( i, j, 0 ); + ids[1] = ids[0] + 1; + } +#define gpXYZ2IJK(METHOD) \ + void METHOD( const gp_XYZ& ijk, cgsize_t* ids ) const { \ + METHOD( int(ijk.X()), int(ijk.Y()), int(ijk.Z()), ids); \ + } + gpXYZ2IJK( IFaceNodes ) + gpXYZ2IJK( JFaceNodes ) + gpXYZ2IJK( KFaceNodes ) + gpXYZ2IJK( IEdgeNodes ) + gpXYZ2IJK( JEdgeNodes ) + }; + + //================================================================================ + /*! + * \brief Iterator over nodes of the structired grid using FORTRAN multidimensional + * array ordering. + */ + class TPointRangeIterator + { + int _beg[3], _end[3], _cur[3], _dir[3], _dim; + bool _more; + public: + TPointRangeIterator( const cgsize_t* range, int dim ):_dim(dim) + { + _more = false; + for ( int i = 0; i < dim; ++i ) + { + _beg[i] = range[i]; + _end[i] = range[i+dim]; + _dir[i] = _end[i] < _beg[i] ? -1 : 1; + _end[i] += _dir[i]; + _cur[i] = _beg[i]; + if ( _end[i] - _beg[i] ) + _more = true; + } +// for ( int i = dim; i < 3; ++i ) +// _cur[i] = _beg[i] = _end[i] = _dir[i] = 0; + } + bool More() const + { + return _more; + } + gp_XYZ Next() + { + gp_XYZ res( _cur[0], _cur[1], _cur[2] ); + for ( int i = 0; i < _dim; ++i ) + { + _cur[i] += _dir[i]; + if ( _cur[i]*_dir[i] < _end[i]*_dir[i] ) + break; + if ( i+1 < _dim ) + _cur[i] = _beg[i]; + else + _more = false; + } + return res; + } + size_t Size() const + { + size_t size = 1; + for ( int i = 0; i < _dim; ++i ) + size *= _dir[i]*(_end[i]-_beg[i]); + return size; + } + gp_XYZ Begin() const { return gp_XYZ( _beg[0], _beg[1], _beg[2] ); } + //gp_XYZ End() const { return gp_XYZ( _end[0]-1, _end[1]-1, _end[2]-1 ); } + }; + + //================================================================================ + /*! + * \brief Reads zone interface connectivity + * \param file - file to read + * \param base - base to read + * \param zone - zone to replace nodes in + * \param zonesByName - TZoneData by name + * \retval string - warning message + * + * see // http://www.grc.nasa.gov/WWW/cgns/CGNS_docs_current/sids/cnct.html + */ + //================================================================================ + + string TZoneData::ReadZonesConnection( int file, + int base, + const map< string, TZoneData >& zonesByName) + { + string error; + + char connectName[ CGNS_NAME_SIZE ], donorName [ CGNS_NAME_SIZE ]; + + // ---------------------------- + // read zone 1 to 1 interfaces + // ---------------------------- + if ( IsStructured() ) + { + int nb1to1 = 0; + if ( cg_n1to1 ( file, base, _id, &nb1to1) == CG_OK ) + { + cgsize_t range[CGNS_STRUCT_RANGE_SZ], donorRange[CGNS_STRUCT_RANGE_SZ]; + int transform[3] = {0,0,0}; + + for ( int I = 1; I <= nb1to1; ++I ) + { + if ( cg_1to1_read(file, base, _id, I, connectName, + donorName, range, donorRange, transform) == CG_OK ) + { + map< string, TZoneData>::const_iterator n_z = zonesByName.find( donorName ); + if ( n_z == zonesByName.end() ) + continue; // donor zone not yet read + const TZoneData& zone2 = n_z->second; + + // set up matrix to transform ijk of the zone to ijk of the zone2 + gp_Mat T; + for ( int i = 0; i < _meshDim; ++i ) + if ( transform[i] ) + { + int row = Abs(transform[i]); + int col = i+1; + int val = transform[i] > 0 ? +1 : -1; + T( row, col ) = val; + } + + // fill nodeReplacementMap + TPointRangeIterator rangeIt1( range, _meshDim ); + TPointRangeIterator rangeIt2( donorRange, _meshDim ); + gp_XYZ begin1 = rangeIt1.Begin(), begin2 = rangeIt2.Begin(), index1, index2; + if ( &zone2 == this ) + { + // not to read twice the same interface with self + TPointRangeIterator rangeIt1bis( range, _meshDim ); + if ( rangeIt1bis.More() ) + { + index1 = rangeIt1bis.Next(); + index2 = T * ( index1 - begin1 ) + begin2; + int node1 = NodeID( index1 ); + int node2 = zone2.NodeID( index2 ); + if ( _nodeReplacementMap.count( node2 ) && + _nodeReplacementMap[ node2 ] == node1 ) + continue; // this interface already read + } + } + while ( rangeIt1.More() ) + { + index1 = rangeIt1.Next(); + index2 = T * ( index1 - begin1 ) + begin2; + int node1 = NodeID( index1 ); + int node2 = zone2.NodeID( index2 ); + _nodeReplacementMap.insert( make_pair( node1, node2 )); + } + } + else + { + error = cg_get_error(); + } + } + } + else + { + error = cg_get_error(); + } + } + + // --------------------------------- + // read general zone connectivities + // --------------------------------- + int nbConn = 0; + if ( cg_nconns( file, base, _id, &nbConn) == CG_OK ) + { + cgsize_t nb, donorNb; + CGNS_ENUMT(GridLocation_t) location; + CGNS_ENUMT(GridConnectivityType_t) connectType; + CGNS_ENUMT(PointSetType_t) ptype, donorPtype; + CGNS_ENUMT(ZoneType_t) donorZonetype; + CGNS_ENUMT(DataType_t) donorDatatype; + + for ( int I = 1; I <= nbConn; ++I ) + { + if ( cg_conn_info(file, base, _id, I, connectName, &location, &connectType, + &ptype, &nb, donorName, &donorZonetype, &donorPtype, + &donorDatatype, &donorNb ) == CG_OK ) + { + if ( location != CGNS_ENUMV( Vertex )) + continue; // we do not support cell-to-cell connectivity + if ( ptype != CGNS_ENUMV( PointList ) && + ptype != CGNS_ENUMV( PointRange )) + continue; + if ( donorPtype != CGNS_ENUMV( PointList ) && + donorPtype != CGNS_ENUMV( PointRange )) + continue; + + map< string, TZoneData>::const_iterator n_z = zonesByName.find( donorName ); + if ( n_z == zonesByName.end() ) + continue; // donor zone not yet read + const TZoneData& zone2 = n_z->second; + + vector< int > ids( nb * IndexSize() ); + vector< int > donorIds( donorNb * zone2.IndexSize() ); + if (cg_conn_read ( file, base, _id, I, + &ids[0], CGNS_ENUMV(Integer), &donorIds[0]) == CG_OK ) + { + for ( int isThisZone = 0; isThisZone < 2; ++isThisZone ) + { + const TZoneData& zone = isThisZone ? *this : zone2; + CGNS_ENUMT(PointSetType_t) type = isThisZone ? ptype : donorPtype; + vector< int >& points = isThisZone ? ids : donorIds; + if ( type == CGNS_ENUMV( PointRange )) + { + TPointRangeIterator rangeIt( &points[0], zone._meshDim ); + points.clear(); + while ( rangeIt.More() ) + points.push_back ( NodeID( rangeIt.Next() )); + } + else if ( zone.IsStructured() ) + { + vector< int > resIDs; resIDs.reserve( points.size() / IndexSize() ); + for ( size_t i = 0; i < points.size(); i += IndexSize() ) + resIDs.push_back( zone.NodeID( points[i+0], points[i+1], points[i+2] )); + resIDs.swap( points ); + } + else if ( zone._nodeIdShift > 0 ) + { + for ( size_t i = 0; i < points.size(); ++i ) + points[i] += zone._nodeIdShift; + } + } + for ( size_t i = 0; i < ids.size() && i < donorIds.size(); ++i ) + _nodeReplacementMap.insert( make_pair( ids[i], donorIds[i] )); + } + else + { + error = cg_get_error(); + } + } + else + { + error = cg_get_error(); + } + } + } + else + { + error = cg_get_error(); + } + return error; + } + + //================================================================================ + /*! + * \brief Replaces node ids according to nodeReplacementMap to take into account + * connection of zones + */ + //================================================================================ + + void TZoneData::ReplaceNodes( cgsize_t* ids, int nbIds, int idShift/* = 0*/ ) const + { + if ( !_nodeReplacementMap.empty() ) + { + map< int, int >::const_iterator it, end = _nodeReplacementMap.end(); + for ( size_t i = 0; i < nbIds; ++i ) + if (( it = _nodeReplacementMap.find( ids[i] + idShift)) != end ) + ids[i] = it->second; + else + ids[i] += idShift; + } + else if ( idShift ) + { + for ( size_t i = 0; i < nbIds; ++i ) + ids[i] += idShift; + } + } + //================================================================================ + /*! + * \brief functions adding an element of a particular type + */ + SMDS_MeshElement* add_0D(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->Add0DElementWithID( ids[0], ID ); + } + SMDS_MeshElement* add_BAR_2(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddEdgeWithID( ids[0], ids[1], ID ); + } + SMDS_MeshElement* add_BAR_3(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddEdgeWithID( ids[0], ids[1], ids[2], ID ); + } + SMDS_MeshElement* add_TRI_3(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddFaceWithID( ids[0], ids[2], ids[1], ID ); + } + SMDS_MeshElement* add_TRI_6(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddFaceWithID( ids[0], ids[2], ids[1], ids[5], ids[4], ids[3], ID ); + } + SMDS_MeshElement* add_QUAD_4(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddFaceWithID( ids[0], ids[3], ids[2], ids[1], ID ); + } + SMDS_MeshElement* add_QUAD_8(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddFaceWithID( ids[0],ids[3],ids[2],ids[1],ids[7],ids[6],ids[5],ids[4], ID ); + } + SMDS_MeshElement* add_TETRA_4(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddVolumeWithID( ids[0], ids[2], ids[1], ids[3], ID ); + } + SMDS_MeshElement* add_TETRA_10(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddVolumeWithID( ids[0],ids[2],ids[1],ids[3],ids[6], + ids[5],ids[4],ids[7],ids[9],ids[8], ID ); + } + SMDS_MeshElement* add_PYRA_5(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ID ); + } + SMDS_MeshElement* add_PYRA_13(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ids[8],ids[7], + ids[6],ids[5],ids[9],ids[12],ids[11],ids[10], ID ); + } + SMDS_MeshElement* add_PENTA_6(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddVolumeWithID( ids[0],ids[2],ids[1],ids[3],ids[5],ids[4], ID ); + } + SMDS_MeshElement* add_PENTA_15(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddVolumeWithID( ids[0],ids[2],ids[1],ids[3],ids[5],ids[4],ids[8],ids[7], + ids[6],ids[9],ids[11],ids[10],ids[14],ids[13],ids[12], ID ); + } + SMDS_MeshElement* add_HEXA_8(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ids[7],ids[6],ids[5], ID ); + } + SMDS_MeshElement* add_HEXA_20(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ids[7],ids[6], + ids[5],ids[11],ids[10],ids[9],ids[8],ids[12],ids[15], + ids[14],ids[13],ids[19],ids[18],ids[17],ids[16], ID ); + } + SMDS_MeshElement* add_NGON(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID) + { + vector idVec( ids[0] ); + for ( int i = 0; i < ids[0]; ++i ) + idVec[ i ] = (int) ids[ i + 1]; + return mesh->AddPolygonalFaceWithID( idVec, ID ); + } + + typedef SMDS_MeshElement* (* PAddElemFun) (cgsize_t* ids, SMESHDS_Mesh* mesh, int ID); + + //================================================================================ + /*! + * \brief Return an array of functions each adding an element of a particular type + */ + //================================================================================ + + PAddElemFun* getAddElemFunTable() + { + static vector< PAddElemFun > funVec; + if ( funVec.empty() ) + { + funVec.resize( NofValidElementTypes, (PAddElemFun)0 ); + funVec[ CGNS_ENUMV( NODE )] = add_0D ; + funVec[ CGNS_ENUMV( BAR_2 )] = add_BAR_2 ; + funVec[ CGNS_ENUMV( BAR_3 )] = add_BAR_3 ; + funVec[ CGNS_ENUMV( TRI_3 )] = add_TRI_3 ; + funVec[ CGNS_ENUMV( TRI_6 )] = add_TRI_6 ; + funVec[ CGNS_ENUMV( QUAD_4 )] = add_QUAD_4 ; + funVec[ CGNS_ENUMV( QUAD_8 )] = add_QUAD_8 ; + funVec[ CGNS_ENUMV( QUAD_9 )] = add_QUAD_8 ; + funVec[ CGNS_ENUMV( TETRA_4 )] = add_TETRA_4 ; + funVec[ CGNS_ENUMV( TETRA_10 )] = add_TETRA_10; + funVec[ CGNS_ENUMV( PYRA_5 )] = add_PYRA_5 ; + funVec[ CGNS_ENUMV( PYRA_13 )] = add_PYRA_13 ; + funVec[ CGNS_ENUMV( PYRA_14 )] = add_PYRA_13 ; + funVec[ CGNS_ENUMV( PENTA_6 )] = add_PENTA_6 ; + funVec[ CGNS_ENUMV( PENTA_15 )] = add_PENTA_15; + funVec[ CGNS_ENUMV( PENTA_18 )] = add_PENTA_15; + funVec[ CGNS_ENUMV( HEXA_8 )] = add_HEXA_8 ; + funVec[ CGNS_ENUMV( HEXA_20 )] = add_HEXA_20 ; + funVec[ CGNS_ENUMV( HEXA_27 )] = add_HEXA_20 ; + funVec[ CGNS_ENUMV( NGON_n )] = add_NGON ; + } + return &funVec[0]; + } + + //================================================================================ + /*! + * \brief Finds an existing boundary element + */ + //================================================================================ + + const SMDS_MeshElement* findElement(const cgsize_t* nodeIDs, + const int nbNodes, + const SMESHDS_Mesh* mesh) + { + const SMDS_MeshNode* nn[4]; // look for quad4 or seg2 + if (( nn[0] = mesh->FindNode( nodeIDs[0] ))) + { + SMDSAbs_ElementType eType = nbNodes==4 ? SMDSAbs_Face : SMDSAbs_Edge; + SMDS_ElemIteratorPtr eIt = nn[0]->GetInverseElementIterator( eType ); + if ( eIt->more() ) + for ( int i = 1; i < nbNodes; ++i ) + nn[i] = mesh->FindNode( nodeIDs[i] ); + while ( eIt->more() ) + { + const SMDS_MeshElement* e = eIt->next(); + if ( e->NbNodes() == nbNodes ) + { + bool elemOK = true; + for ( int i = 1; i < nbNodes && elemOK; ++i ) + elemOK = ( e->GetNodeIndex( nn[i] ) >= 0 ); + if ( elemOK ) + return e; + } + } + } + return 0; + } + +} // namespace + +//================================================================================ +/*! + * \brief Perform reading a myMeshId-th mesh + */ +//================================================================================ + +Driver_Mesh::Status DriverCGNS_Read::Perform() +{ + myErrorMessages.clear(); + + Status aResult; + if (( aResult = open() ) != DRS_OK ) + return aResult; + + // read nb of meshes (CGNSBase_t) + if ( myMeshId < 0 || myMeshId >= GetNbMeshes(aResult)) + return addMessage( SMESH_Comment("Invalid mesh index :") << myMeshId ); + + // read a name and a dimension of the mesh + const int cgnsBase = myMeshId + 1; + char meshName[CGNS_NAME_SIZE]; + int meshDim, spaceDim; + if ( cg_base_read( _fn, cgnsBase, meshName, &meshDim, &spaceDim) != CG_OK ) + return addMessage( cg_get_error() ); + + if ( spaceDim < 1 || spaceDim > 3 ) + return addMessage( SMESH_Comment("Invalid space dimension: ") << spaceDim + << " in mesh '" << meshName << "'"); + + myMeshName = meshName; + + // read nb of domains (Zone_t) in the mesh + int nbZones = 0; + if ( cg_nzones (_fn, cgnsBase, &nbZones) != CG_OK ) + return addMessage( cg_get_error() ); + + if ( nbZones < 1 ) + return addMessage( SMESH_Comment("Empty mesh: '") << meshName << "'"); + + // read the domains (zones) + // ------------------------ + map< string, TZoneData > zonesByName; + char name[CGNS_NAME_SIZE]; + cgsize_t sizes[NB_ZONE_SIZE_VAL]; + memset(sizes, 0, NB_ZONE_SIZE_VAL * sizeof(cgsize_t)); + + const SMDS_MeshInfo& meshInfo = myMesh->GetMeshInfo(); + int groupID = myMesh->GetGroups().size(); + + for ( int iZone = 1; iZone <= nbZones; ++iZone ) + { + // size and name of a zone + if ( cg_zone_read( _fn, cgnsBase, iZone, name, sizes) != CG_OK) { + addMessage( cg_get_error() ); + continue; + } + TZoneData& zone = zonesByName[ name ]; + zone._id = iZone; + zone._nodeIdShift = meshInfo.NbNodes(); + zone._elemIdShift = meshInfo.NbElements(); + zone.SetSizeAndDim( sizes, meshDim ); + + // mesh type of the zone + if ( cg_zone_type ( _fn, cgnsBase, iZone, &zone._type) != CG_OK) { + addMessage( cg_get_error() ); + continue; + } + + switch ( zone._type ) + { + case CGNS_ENUMV( Unstructured ): + case CGNS_ENUMV( Structured ): + break; + case CGNS_ENUMV( ZoneTypeNull ): + addMessage( "Meshes with ZoneTypeNull are not supported"); + continue; + case CGNS_ENUMV( ZoneTypeUserDefined ): + addMessage( "Meshes with ZoneTypeUserDefined are not supported"); + continue; + default: + addMessage( "Unknown ZoneType_t"); + continue; + } + + // ----------- + // Read nodes + // ----------- + + if ( cg_ncoords( _fn, cgnsBase, iZone, &spaceDim) != CG_OK ) { + addMessage( cg_get_error() ); + continue; + } + if ( spaceDim < 1 ) { + addMessage( SMESH_Comment("No coordinates defined in zone ") + << iZone << " of Mesh " << myMeshId ); + continue; + } + // read coordinates + + int rmin[3] = {1,1,1}; // range of nodes to read + int rmax[3] = {1,1,1}; + int nbNodes = rmax[0] = zone._sizes[0]; + if ( zone.IsStructured()) + for ( int i = 1; i < meshDim; ++i ) + nbNodes *= rmax[i] = zone._sizes[i]; + + vector coords[3]; + for ( int c = 1; c <= spaceDim; ++c) + { + coords[c-1].resize( nbNodes ); + + CGNS_ENUMV( DataType_t ) type; + if ( cg_coord_info( _fn, cgnsBase, iZone, c, &type, name) != CG_OK || + cg_coord_read( _fn, cgnsBase, iZone, name, CGNS_ENUMV(RealDouble), + rmin, rmax, (void*)&(coords[c-1][0])) != CG_OK) + { + addMessage( cg_get_error() ); + coords[c-1].clear(); + break; + } + } + if ( coords[ spaceDim-1 ].empty() ) + continue; // there was an error while reading coordinates + + // fill coords with zero if spaceDim < 3 + for ( int c = 2; c <= 3; ++c) + if ( coords[ c-1 ].empty() ) + coords[ c-1 ].resize( nbNodes, 0.0 ); + + // create nodes + try { + for ( int i = 0; i < nbNodes; ++i ) + myMesh->AddNodeWithID( coords[0][i], coords[1][i], coords[2][i], i+1+zone._nodeIdShift ); + } + catch ( std::exception& exc ) // expect std::bad_alloc + { + addMessage( exc.what() ); + break; + } + + // Read connectivity between zones. Nodes of the zone interface will be + // replaced withing the zones read later + string err = zone.ReadZonesConnection( _fn, cgnsBase, zonesByName ); + if ( !err.empty() ) + addMessage( err ); + + // -------------- + // Read elements + // -------------- + if ( zone.IsStructured()) + { + int nbI = zone._sizeX - 1, nbJ = zone._sizeY - 1, nbK = zone._sizeZ - 1; + cgsize_t nID[8]; + if ( meshDim > 2 && nbK > 0 ) + { + for ( int k = 1; k <= nbK; ++k ) + for ( int j = 1; j <= nbJ; ++j ) + for ( int i = 1; i <= nbI; ++i ) + { + zone.CellNodes( i, j, k, nID ); + zone.ReplaceNodes( nID, 8 ); + myMesh->AddVolumeWithID(nID[0],nID[1],nID[2],nID[3],nID[4],nID[5],nID[6],nID[7], + meshInfo.NbElements()+1); + } + } + else if ( meshDim > 1 && nbJ > 0 ) + { + for ( int j = 1; j <= nbJ; ++j ) + for ( int i = 1; i <= nbI; ++i ) + { + zone.CellNodes( i, j, nID ); + zone.ReplaceNodes( nID, 4 ); + myMesh->AddFaceWithID(nID[0],nID[1],nID[2],nID[3], meshInfo.NbElements()+1); + } + } + else if ( meshDim > 0 && nbI > 0 ) + { + nID[0] = zone.NodeID( 1, 0, 0 ); + for ( int i = 1; i <= nbI; ++i, ++nID[0] ) + { + nID[1] = nID[0]+1; + zone.ReplaceNodes( nID, 2 ); + myMesh->AddEdgeWithID(nID[0],nID[1], meshInfo.NbElements()+1); + } + } + } + else + { + // elements can be stored in different sections each dedicated to one element type + int nbSections = 0; + if ( cg_nsections( _fn, cgnsBase, iZone, &nbSections) != CG_OK) + { + addMessage( cg_get_error() ); + continue; + } + PAddElemFun* addElemFuns = getAddElemFunTable(), curAddElemFun = 0; + int nbNotSuppElem = 0; // nb elements of not supported types + bool polyhedError = false; // error at polyhedron creation + + // read element data + + CGNS_ENUMT( ElementType_t ) elemType; + cgsize_t start, end; // range of ids of elements of a zone + int nbBnd, parent_flag, eDataSize = 0; + for ( int iSec = 1; iSec <= nbSections; ++iSec ) + { + if ( cg_section_read( _fn, cgnsBase, iZone, iSec, name, &elemType, + &start, &end, &nbBnd, &parent_flag) != CG_OK || + cg_ElementDataSize( _fn, cgnsBase, iZone, iSec, &eDataSize ) != CG_OK ) + { + addMessage( cg_get_error() ); + continue; + } + vector< cgsize_t > elemData( eDataSize ); + if ( cg_elements_read( _fn, cgnsBase, iZone, iSec, &elemData[0], NULL ) != CG_OK ) + { + addMessage( cg_get_error() ); + continue; + } + // store elements + + int pos = 0, cgnsNbNodes = 0, elemID = start + zone._elemIdShift; + cg_npe( elemType, &cgnsNbNodes ); // get nb nodes by element type + curAddElemFun = addElemFuns[ elemType ]; + SMDS_MeshElement* newElem = 0; + const SMDS_MeshElement* face; + + while ( pos < eDataSize ) + { + CGNS_ENUMT( ElementType_t ) currentType = elemType; + if ( currentType == CGNS_ENUMV( MIXED )) { + //ElementConnectivity = Etype1, Node11, Node21, ... NodeN1, + // Etype2, Node12, Node22, ... NodeN2, + // ... + // EtypeM, Node1M, Node2M, ... NodeNM + currentType = (CGNS_ENUMT(ElementType_t)) elemData[ pos++ ]; + cg_npe( currentType, &cgnsNbNodes ); + curAddElemFun = addElemFuns[ currentType ]; + } + if ( cgnsNbNodes < 1 ) // poly elements + { + if ( currentType == CGNS_ENUMV( NFACE_n )) // polyhedron + { + //ElementConnectivity = Nfaces1, Face11, Face21, ... FaceN1, + // Nfaces2, Face12, Face22, ... FaceN2, + // ... + // NfacesM, Face1M, Face2M, ... FaceNM + const int nbFaces = elemData[ pos++ ]; + vector quantities( nbFaces ); + vector nodes, faceNodes; + nodes.reserve( nbFaces * 4 ); + for ( int iF = 0; iF < nbFaces; ++iF ) + { + const int faceID = Abs( elemData[ pos++ ]) + zone._elemIdShift; + if (( face = myMesh->FindElement( faceID )) && face->GetType() == SMDSAbs_Face ) + { + const bool reverse = ( elemData[ pos-1 ] < 0 ); + const int iQuad = face->IsQuadratic() ? 1 : 0; + SMDS_ElemIteratorPtr nIter = face->interlacedNodesElemIterator(); + faceNodes.assign( SMDS_MeshElement::iterator( nIter ), + SMDS_MeshElement::iterator()); + if ( iQuad && reverse ) + nodes.push_back( faceNodes[0] ); + if ( reverse ) + nodes.insert( nodes.end(), faceNodes.rbegin(), faceNodes.rend() - iQuad ); + else + nodes.insert( nodes.end(), faceNodes.begin(), faceNodes.end() ); + + quantities[ iF ] = face->NbNodes(); + } + else { + polyhedError = true; + break; + } + } + if ( quantities.back() ) + { + myMesh->AddPolyhedralVolumeWithID( nodes, quantities, elemID ); + } + } + else if ( currentType == CGNS_ENUMV( NGON_n )) // polygon + { + // ElementConnectivity = Nnodes1, Node11, Node21, ... NodeN1, + // Nnodes2, Node12, Node22, ... NodeN2, + // ... + // NnodesM, Node1M, Node2M, ... NodeNM + cgnsNbNodes = elemData[ pos ]; + zone.ReplaceNodes( &elemData[pos+1], cgnsNbNodes, zone._nodeIdShift ); + newElem = add_NGON( &elemData[pos ], myMesh, elemID ); + pos += cgnsNbNodes + 1; + cgnsNbNodes = 0; // as mark of poly elements + } + } + else // standard elements + { + zone.ReplaceNodes( &elemData[pos], cgnsNbNodes, zone._nodeIdShift ); + newElem = curAddElemFun( &elemData[pos], myMesh, elemID ); + pos += cgnsNbNodes; + nbNotSuppElem += int( newElem && newElem->NbNodes() != cgnsNbNodes ); + } + elemID++; + + } // loop on elemData + } // loop on cgns sections + + if ( nbNotSuppElem > 0 ) + addMessage( SMESH_Comment(nbNotSuppElem) << " elements of not supported types" + << " have beem converted to close types"); + if ( polyhedError ) + addMessage( "Some polyhedral elements have been skipped due to internal(?) errors" ); + + } // reading unstructured elements + + zone._nbNodes = meshInfo.NbNodes() - zone._nodeIdShift; + zone._nbElems = meshInfo.NbElements() - zone._elemIdShift; + + // ------------------------------------------- + // Read Boundary Conditions into SMESH groups + // ------------------------------------------- + int nbBC = 0; + if ( cg_nbocos( _fn, cgnsBase, iZone, &nbBC) == CG_OK ) + { + CGNS_ENUMT( BCType_t ) bcType; + CGNS_ENUMT( PointSetType_t ) psType; + CGNS_ENUMT( DataType_t ) normDataType; + cgsize_t nbPnt, normFlag; + int normIndex[3], nbDS; + for ( int iBC = 1; iBC <= nbBC; ++iBC ) + { + if ( cg_boco_info( _fn, cgnsBase, iZone, iBC, name, &bcType, &psType, + &nbPnt, normIndex, &normFlag, &normDataType, &nbDS ) != CG_OK ) + { + addMessage( cg_get_error() ); + continue; + } + vector< cgsize_t > ids( nbPnt * zone.IndexSize() ); + CGNS_ENUMT( GridLocation_t ) location; + if ( cg_boco_read( _fn, cgnsBase, iZone, iBC, &ids[0], NULL ) != CG_OK || + cg_boco_gridlocation_read( _fn, cgnsBase, iZone, iBC, &location) != CG_OK ) + { + addMessage( cg_get_error() ); + continue; + } + SMDSAbs_ElementType elemType = SMDSAbs_All; + switch ( location ) { + case CGNS_ENUMV( Vertex ): elemType = SMDSAbs_Node; break; + case CGNS_ENUMV( FaceCenter ): elemType = SMDSAbs_Face; break; + case CGNS_ENUMV( IFaceCenter ): elemType = SMDSAbs_Face; break; + case CGNS_ENUMV( JFaceCenter ): elemType = SMDSAbs_Face; break; + case CGNS_ENUMV( KFaceCenter ): elemType = SMDSAbs_Face; break; + case CGNS_ENUMV( EdgeCenter ): elemType = SMDSAbs_Edge; break; + default:; + } + SMESHDS_Group* group = new SMESHDS_Group ( groupID++, myMesh, elemType ); + myMesh->AddGroup( group ); + SMESH_Comment groupName( name ); groupName << " " << cg_BCTypeName( bcType ); + group->SetStoreName( groupName.c_str() ); + SMDS_MeshGroup& groupDS = group->SMDSGroup(); + + if ( elemType == SMDSAbs_Node ) + { + if ( zone.IsStructured() ) + { + vector< cgsize_t > nodeIds; + if ( psType == CGNS_ENUMV( PointRange )) + { + // nodes are given as (ijkMin, ijkMax) + TPointRangeIterator idIt( & ids[0], meshDim ); + nodeIds.reserve( idIt.Size() ); + while ( idIt.More() ) + nodeIds.push_back( zone.NodeID( idIt.Next() )); + } + else + { + // nodes are given as (ijk1, ijk2, ..., ijkN) + nodeIds.reserve( ids.size() / meshDim ); + for ( size_t i = 0; i < ids.size(); i += meshDim ) + nodeIds.push_back( zone.NodeID( ids[i], ids[i+1], ids[i+2] )); + } + ids.swap( nodeIds ); + } + else if ( zone._nodeIdShift ) + { + for ( size_t i = 0; i < ids.size(); ++i ) + ids[i] += zone._nodeIdShift; + } + zone.ReplaceNodes( &ids[0], ids.size() ); + + for ( size_t i = 0; i < ids.size(); ++i ) + if ( const SMDS_MeshNode* n = myMesh->FindNode( ids[i] )) + groupDS.Add( n ); + } + else // BC applied to elements + { + if ( zone.IsStructured() ) + { + int axis = 0; // axis perpendiculaire to which boundary elements are oriented + if ( ids.size() >= meshDim * 2 ) + { + for ( ; axis < meshDim; ++axis ) + if ( ids[axis] - ids[axis+meshDim] == 0 ) + break; + } + else + { + for ( ; axis < meshDim; ++axis ) + if ( normIndex[axis] != 0 ) + break; + } + if ( axis == meshDim ) + { + addMessage( SMESH_Comment("Invalid NormalIndex in BC ") << name ); + continue; + } + const int nbElemNodesByDim[] = { 1, 2, 4, 8 }; + const int nbElemNodes = nbElemNodesByDim[ meshDim ]; + + if ( psType == CGNS_ENUMV( PointRange ) || + psType == CGNS_ENUMV( ElementRange )) + { + // elements are given as (ijkMin, ijkMax) + typedef void (TZoneData::*PGetNodesFun)( const gp_XYZ& ijk, cgsize_t* ids ) const; + PGetNodesFun getNodesFun = 0; + if ( elemType == SMDSAbs_Face && meshDim == 3 ) + switch ( axis ) { + case 0: getNodesFun = & TZoneData::IFaceNodes; + case 1: getNodesFun = & TZoneData::JFaceNodes; + case 2: getNodesFun = & TZoneData::KFaceNodes; + } + else if ( elemType == SMDSAbs_Edge && meshDim == 2 ) + switch ( axis ) { + case 0: getNodesFun = & TZoneData::IEdgeNodes; + case 1: getNodesFun = & TZoneData::JEdgeNodes; + } + if ( !getNodesFun ) + { + addMessage( SMESH_Comment("Unsupported BC location in BC ") << name + << " " << cg_GridLocationName( location ) + << " in " << meshDim << " mesh"); + continue; + } + TPointRangeIterator rangeIt( & ids[0], meshDim ); + vector< cgsize_t > elemNodeIds( rangeIt.Size() * nbElemNodes ); + for ( int i = 0; rangeIt.More(); i+= nbElemNodes ) + (zone.*getNodesFun)( rangeIt.Next(), &elemNodeIds[i] ); + + ids.swap( elemNodeIds ); + } + else + { + // elements are given as (ijk1, ijk2, ..., ijkN) + typedef void (TZoneData::*PGetNodesFun)( int i, int j, int k, cgsize_t* ids ) const; + PGetNodesFun getNodesFun = 0; + if ( elemType == SMDSAbs_Face ) + switch ( axis ) { + case 0: getNodesFun = & TZoneData::IFaceNodes; + case 1: getNodesFun = & TZoneData::JFaceNodes; + case 2: getNodesFun = & TZoneData::KFaceNodes; + } + else if ( elemType == SMDSAbs_Edge && meshDim == 2 ) + switch ( axis ) { + case 0: getNodesFun = & TZoneData::IEdgeNodes; + case 1: getNodesFun = & TZoneData::JEdgeNodes; + } + if ( !getNodesFun ) + { + addMessage( SMESH_Comment("Unsupported BC location in BC ") << name + << " " << cg_GridLocationName( location ) + << " in " << meshDim << " mesh"); + continue; + } + vector< cgsize_t > elemNodeIds( ids.size()/meshDim * nbElemNodes ); + for ( size_t i = 0, j = 0; i < ids.size(); i += meshDim, j += nbElemNodes ) + (zone.*getNodesFun)( ids[i], ids[i+1], ids[i+2], &elemNodeIds[j] ); + + ids.swap( elemNodeIds ); + } + zone.ReplaceNodes( &ids[0], ids.size() ); + + PAddElemFun addElemFun = 0; + switch ( meshDim ) { + case 1: addElemFun = & add_BAR_2; + case 2: addElemFun = & add_QUAD_4; + case 3: addElemFun = & add_HEXA_8; + } + int elemID = meshInfo.NbElements(); + const SMDS_MeshElement* elem = 0; + for ( size_t i = 0; i < ids.size(); i += nbElemNodes ) + { + if ( iZone == 1 || !( elem = findElement( &ids[i], nbElemNodes, myMesh ))) + elem = addElemFun( &ids[i], myMesh, ++elemID ); + groupDS.Add( elem ); + } + } + else // unstructured zone + { + if ( zone._elemIdShift ) + for ( size_t i = 0; i < ids.size(); ++i ) + ids[i] += zone._elemIdShift; + + if ( psType == CGNS_ENUMV( PointRange ) && ids.size() == 2 ) + { + for ( size_t i = ids[0]; i <= ids[1]; ++i ) + if ( const SMDS_MeshElement* e = myMesh->FindElement( i )) + groupDS.Add( e ); + } + else + { + for ( size_t i = 0; i < ids.size(); ++i ) + if ( const SMDS_MeshElement* e = myMesh->FindElement( ids[i] )) + groupDS.Add( e ); + } + } + } // end "BC applied to elements" + + // to have group type according to a real elem type + group->SetType( groupDS.GetType() ); + + } // loop on BCs of the zone + } + else + { + addMessage( cg_get_error() ); + } + } // loop on the zones of a mesh + + + // ------------------------------------------------------------------------ + // Make groups for multiple zones and remove free nodes at zone interfaces + // ------------------------------------------------------------------------ + map< string, TZoneData >::iterator nameZoneIt = zonesByName.begin(); + for ( ; nameZoneIt != zonesByName.end(); ++nameZoneIt ) + { + TZoneData& zone = nameZoneIt->second; + if ( zone._nbElems == 0 ) continue; + if ( zone._nbElems == meshInfo.NbElements() ) break; // there is only one non-empty zone + + // make a group + SMDSAbs_ElementType elemType = myMesh->GetElementType( zone._elemIdShift + 1, + /*iselem=*/true ); + SMESHDS_Group* group = new SMESHDS_Group ( groupID++, myMesh, elemType ); + myMesh->AddGroup( group ); + group->SetStoreName( nameZoneIt->first.c_str() ); + SMDS_MeshGroup& groupDS = group->SMDSGroup(); + + for ( int i = 1; i <= zone._nbElems; ++i ) + if ( const SMDS_MeshElement* e = myMesh->FindElement( i + zone._elemIdShift )) + groupDS.Add( e ); + + // remove free nodes + map< int, int >::iterator nnRmKeepIt = zone._nodeReplacementMap.begin(); + for ( ; nnRmKeepIt != zone._nodeReplacementMap.end(); ++nnRmKeepIt ) + if ( const SMDS_MeshNode* n = myMesh->FindNode( nnRmKeepIt->first )) + if ( n->NbInverseElements() == 0 ) + myMesh->RemoveFreeNode( n, (SMESHDS_SubMesh *)0, /*fromGroups=*/false ); + } + + aResult = myErrorMessages.empty() ? DRS_OK : DRS_WARN_SKIP_ELEM; + + return aResult; +} + +//================================================================================ +/*! + * \brief Constructor + */ +//================================================================================ + +DriverCGNS_Read::DriverCGNS_Read() +{ + _fn = -1; +} +//================================================================================ +/*! + * \brief Close the cgns file at destruction + */ +//================================================================================ + +DriverCGNS_Read::~DriverCGNS_Read() +{ + if ( _fn > 0 ) + cg_close( _fn ); +} + +//================================================================================ +/*! + * \brief Opens myFile + */ +//================================================================================ + +Driver_Mesh::Status DriverCGNS_Read::open() +{ + if ( _fn < 0 ) + { + +#ifdef CG_MODE_READ + int res = cg_open(myFile.c_str(), CG_MODE_READ, &_fn); +#else + int res = cg_open(myFile.c_str(), MODE_READ, &_fn); +#endif + if ( res != CG_OK) + { + addMessage( cg_get_error(), /*fatal = */true ); + } + } + return _fn >= 0 ? DRS_OK : DRS_FAIL; +} + +//================================================================================ +/*! + * \brief Reads nb of meshes in myFile + */ +//================================================================================ + +int DriverCGNS_Read::GetNbMeshes(Status& theStatus) +{ + if (( theStatus = open()) != DRS_OK ) + return 0; + + int nbases = 0; + if(cg_nbases( _fn, &nbases) != CG_OK) + theStatus = addMessage( cg_get_error(), /*fatal = */true ); + + return nbases; +} diff --git a/src/DriverCGNS/DriverCGNS_Read.hxx b/src/DriverCGNS/DriverCGNS_Read.hxx new file mode 100644 index 000000000..718ba117d --- /dev/null +++ b/src/DriverCGNS/DriverCGNS_Read.hxx @@ -0,0 +1,59 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : DriverCGNS_Read.hxx +// Created : Thu Jun 30 10:25:09 2011 +// Author : Edward AGAPOV (eap) + +#ifndef __DriverCGNS_Read_HXX__ +#define __DriverCGNS_Read_HXX__ + +#include "SMESH_DriverCGNS.hxx" + +#include "Driver_SMESHDS_Mesh.h" + +#include +#include + +/*! + * \brief Driver reading a mesh from the CGNS file. The mesh to read is selected by + * an index (counted form 0) set via SetMeshId() + */ +class MESHDriverCGNS_EXPORT DriverCGNS_Read : public Driver_SMESHDS_Mesh +{ +public: + + DriverCGNS_Read(); + ~DriverCGNS_Read(); + + virtual Status Perform(); + + int GetNbMeshes(Status& theStatus); + + +private: + + Status open(); + + int _fn; //!< file index +}; + +#endif diff --git a/src/DriverCGNS/DriverCGNS_Write.cxx b/src/DriverCGNS/DriverCGNS_Write.cxx new file mode 100644 index 000000000..0c9a20970 --- /dev/null +++ b/src/DriverCGNS/DriverCGNS_Write.cxx @@ -0,0 +1,570 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : DriverCGNS_Write.cxx +// Created : Fri Aug 5 17:43:54 2011 +// Author : Edward AGAPOV (eap) + +#include "DriverCGNS_Write.hxx" + +#include "SMDS_MeshNode.hxx" +#include "SMDS_VolumeTool.hxx" +#include "SMESHDS_GroupBase.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESH_Comment.hxx" + +#include +#include + +#if CGNS_VERSION < 3100 +# define cgsize_t int +#endif + +using namespace std; + +namespace +{ + //================================================================================ + /*! + * \brief Return interlace and type of CGNS element for the given SMDSAbs_EntityType + */ + //================================================================================ + + const int* getInterlaceAndType( const SMDSAbs_EntityType smType, + CGNS_ENUMT( ElementType_t ) & cgType ) + { + static vector< const int* > interlaces; + static vector< CGNS_ENUMT( ElementType_t )> cgTypes; + if ( interlaces.empty() ) + { + interlaces.resize( SMDSEntity_Last, 0 ); + cgTypes.resize( SMDSEntity_Last, CGNS_ENUMV( ElementTypeNull )); + { + static int ids[] = {0}; + interlaces[SMDSEntity_0D] = ids; + cgTypes [SMDSEntity_0D] = CGNS_ENUMV( NODE ); + } + { + static int ids[] = { 0, 1 }; + interlaces[SMDSEntity_Edge] = ids; + cgTypes [SMDSEntity_Edge] = CGNS_ENUMV( BAR_2 ); + } + { + static int ids[] = { 0, 1, 2 }; + interlaces[SMDSEntity_Quad_Edge] = ids; + cgTypes [SMDSEntity_Quad_Edge] = CGNS_ENUMV( BAR_3 ); + } + { + static int ids[] = { 0, 2, 1 }; + interlaces[SMDSEntity_Triangle] = ids; + cgTypes [SMDSEntity_Triangle] = CGNS_ENUMV( TRI_3 ); + } + { + static int ids[] = { 0, 2, 1, 5, 4, 3 }; + interlaces[SMDSEntity_Quad_Triangle] = ids; + cgTypes [SMDSEntity_Quad_Triangle] = CGNS_ENUMV( TRI_6 ); + } + { + static int ids[] = { 0, 3, 2, 1 }; + interlaces[SMDSEntity_Quadrangle] = ids; + cgTypes [SMDSEntity_Quadrangle] = CGNS_ENUMV( QUAD_4 ); + } + { + static int ids[] = { 0,3,2,1,7,6,5,4 }; + interlaces[SMDSEntity_Quad_Quadrangle] = ids; + cgTypes [SMDSEntity_Quad_Quadrangle] = CGNS_ENUMV( QUAD_8 ); + } + { + static int ids[] = { 0, 2, 1, 3 }; + interlaces[SMDSEntity_Tetra] = ids; + cgTypes [SMDSEntity_Tetra] = CGNS_ENUMV( TETRA_4 ); + } + { + static int ids[] = { 0,2,1,3,6,5,4,7,9,8 }; + interlaces[SMDSEntity_Quad_Tetra] = ids; + cgTypes [SMDSEntity_Quad_Tetra] = CGNS_ENUMV( TETRA_10 ); + } + { + static int ids[] = { 0,3,2,1,4 }; + interlaces[SMDSEntity_Pyramid] = ids; + cgTypes [SMDSEntity_Pyramid] = CGNS_ENUMV( PYRA_5 ); + } + { + static int ids[] = { 0,3,2,1,4,8,7,6,5,9,12,11,10 }; + interlaces[SMDSEntity_Quad_Pyramid] = ids; + cgTypes [SMDSEntity_Quad_Pyramid] = CGNS_ENUMV( PYRA_13 ); + } + { + static int ids[] = { 0,2,1,3,5,4 }; + interlaces[SMDSEntity_Penta] = ids; + cgTypes [SMDSEntity_Penta] = CGNS_ENUMV( PENTA_6 ); + } + { + static int ids[] = { 0,2,1,3,5,4,8,7,6,9,11,10,14,13,12 }; + interlaces[SMDSEntity_Quad_Penta] = ids; + cgTypes [SMDSEntity_Quad_Penta] = CGNS_ENUMV( PENTA_15 ); + } + { + static int ids[] = { 0,3,2,1,4,7,6,5 }; + interlaces[SMDSEntity_Hexa] = ids; + cgTypes [SMDSEntity_Hexa] = CGNS_ENUMV( HEXA_8 ); + } + { + static int ids[] = { 0,3,2,1,4,7,6,5,11,10,9,8,12,15,14,13,19,18,17,16 }; + interlaces[SMDSEntity_Quad_Hexa] = ids; + cgTypes [SMDSEntity_Quad_Hexa] = CGNS_ENUMV( HEXA_20 ); + } + { + cgTypes[SMDSEntity_Polygon] = CGNS_ENUMV( NGON_n ); + cgTypes[SMDSEntity_Polyhedra] = CGNS_ENUMV( NFACE_n ); + } + } + cgType = cgTypes[ smType ]; + return interlaces[ smType ]; + } + + //================================================================================ + /*! + * \brief Cut off type of boundary condition from the group name + */ + //================================================================================ + + CGNS_ENUMT( BCType_t ) getBCType( string& groupName ) + { + CGNS_ENUMT( BCType_t ) bcType = CGNS_ENUMV( BCGeneral ); // default type + + // boundary condition type starts from "BC" + size_t bcBeg = groupName.find("BC"); + if ( bcBeg != string::npos ) + { + for ( int t = 0; t < NofValidBCTypes; ++t ) + { + CGNS_ENUMT( BCType_t ) type = CGNS_ENUMT( BCType_t)( t ); + string typeName = cg_BCTypeName( type ); + if ( typeName == &groupName[0] + bcBeg ) + { + bcType = type; + while ( bcBeg > 0 && isspace( bcBeg-1 )) + --bcBeg; + if ( bcBeg == 0 ) + groupName = "Group"; + else + groupName = groupName.substr( 0, bcBeg-1 ); + } + } + } + return bcType; + } + + //================================================================================ + /*! + * \brief Sortable face of a polyhedron + */ + struct TPolyhedFace + { + int _id; // id of NGON_n + vector< int > _nodes; // lowest node IDs used for sorting + + TPolyhedFace( const SMDS_MeshNode** nodes, const int nbNodes, int ID):_id(ID) + { + set< int > ids; + for ( int i = 0; i < nbNodes; ++i ) + ids.insert( nodes[i]->GetID() ); + + _nodes.resize( 3 ); // std::min( nbNodes, 4 )); hope 3 nodes is enough + set< int >::iterator idIt = ids.begin(); + for ( size_t j = 0; j < _nodes.size(); ++j, ++idIt ) + _nodes[j] = *idIt; + } + bool operator< (const TPolyhedFace& o ) const + { + return _nodes < o._nodes; + } + }; + //================================================================================ + /*! + * \brief Return CGNS id of an element + */ + //================================================================================ + + cgsize_t cgnsID( const SMDS_MeshElement* elem, + const map< const SMDS_MeshElement*, cgsize_t >& elem2cgID ) + { + map< const SMDS_MeshElement*, cgsize_t >::const_iterator e2id = elem2cgID.find( elem ); + return ( e2id == elem2cgID.end() ? elem->GetID() : e2id->second ); + } + +} // namespace + +//================================================================================ +/*! + * \brief Write the mesh into the CGNS file + */ +//================================================================================ + +Driver_Mesh::Status DriverCGNS_Write::Perform() +{ + myErrorMessages.clear(); + + if ( !myMesh || myMesh->GetMeshInfo().NbElements() < 1 ) + return addMessage( !myMesh ? "NULL mesh" : "Empty mesh (no elements)", /*fatal = */true ); + + // open the file + if ( cg_open(myFile.c_str(), CG_MODE_MODIFY, &_fn) != CG_OK && + cg_open(myFile.c_str(), CG_MODE_WRITE, &_fn) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + + // create a Base + // -------------- + + const int spaceDim = 3; + int meshDim = 1; + if ( myMesh->NbFaces() > 0 ) meshDim = 2; + if ( myMesh->NbVolumes() > 0 ) meshDim = 3; + + if ( myMeshName.empty() ) + { + int nbases = 0; + if ( cg_nbases( _fn, &nbases) == CG_OK) + myMeshName = ( SMESH_Comment("Base_") << nbases+1 ); + else + myMeshName = "Base_0"; + } + int iBase; + if ( cg_base_write( _fn, myMeshName.c_str(), meshDim, spaceDim, &iBase)) + return addMessage( cg_get_error(), /*fatal = */true ); + + // create a Zone + // -------------- + + int nbCells = myMesh->NbEdges(); + if ( meshDim == 3 ) + nbCells = myMesh->NbVolumes(); + else if ( meshDim == 2 ) + nbCells = myMesh->NbFaces(); + + cgsize_t size[9] = { myMesh->NbNodes(), nbCells, /*NBoundVertex=*/0, 0,0,0,0,0,0 }; + int iZone; + if ( cg_zone_write( _fn, iBase, "SMESH_Mesh", size, + CGNS_ENUMV( Unstructured ), &iZone) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + + // Map to store only elements whose an SMDS ID differs from a CGNS one + typedef map< const SMDS_MeshElement*, cgsize_t > TElem2cgIDMap; + vector< TElem2cgIDMap > elem2cgIDByEntity( SMDSEntity_Last ); + TElem2cgIDMap::iterator elem2cgIDIter; + + TElem2cgIDMap & n2cgID = elem2cgIDByEntity[ SMDSEntity_Node ]; + + // Write nodes + // ------------ + { + vector< double > coords( myMesh->NbNodes() ); + int iC; + // X + SMDS_NodeIteratorPtr nIt = myMesh->nodesIterator( /*idInceasingOrder=*/true ); + for ( int i = 0; nIt->more(); ++i ) coords[i] = nIt->next()->X(); + if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble), + "CoordinateX", &coords[0], &iC) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + // Y + nIt = myMesh->nodesIterator( /*idInceasingOrder=*/true ); + for ( int i = 0; nIt->more(); ++i ) coords[i] = nIt->next()->Y(); + if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble), + "CoordinateY", &coords[0], &iC) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + // Z + nIt = myMesh->nodesIterator( /*idInceasingOrder=*/true ); + for ( int i = 0; nIt->more(); ++i ) coords[i] = nIt->next()->Z(); + if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble), + "CoordinateZ", &coords[0], &iC) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + + // store CGNS ids of nodes + nIt = myMesh->nodesIterator( /*idInceasingOrder=*/true ); + for ( int i = 0; nIt->more(); ++i ) + { + const SMDS_MeshElement* n = nIt->next(); + if ( n->GetID() != i+1 ) + n2cgID.insert( n2cgID.end(), make_pair( n, i+1 )); + } + } + // Write elements + // --------------- + + cgsize_t cgID = 1, startID; + + // write into a section all successive elements of one geom type + int iSec; + vector< cgsize_t > elemData; + SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(); + const SMDS_MeshElement* elem = elemIt->next(); + while ( elem ) + { + const SMDSAbs_EntityType elemType = elem->GetEntityType(); + CGNS_ENUMT( ElementType_t ) cgType; + const int* interlace = getInterlaceAndType( elemType, cgType ); + + TElem2cgIDMap & elem2cgID = elem2cgIDByEntity[ elemType ]; + + elemData.clear(); + startID = cgID; + + if ( interlace ) // STANDARD elements + do + { + for ( int i = 0, nb = elem->NbNodes(); i < nb; ++i ) + elemData.push_back( cgnsID( elem->GetNode( interlace[i] ), n2cgID )); + if ( elem->GetID() != cgID ) + elem2cgID.insert( elem2cgID.end(), make_pair( elem, cgID )); + ++cgID; + elem = elemIt->more() ? elemIt->next() : 0; + } + while ( elem && elem->GetEntityType() == elemType ); + + else if ( elemType == SMDSEntity_Polygon ) // POLYGONS + do + { + elemData.push_back( elem->NbNodes() ); + for ( int i = 0, nb = elem->NbNodes(); i < nb; ++i ) + elemData.push_back( cgnsID( elem->GetNode(i), n2cgID )); + if ( elem->GetID() != cgID ) + elem2cgID.insert( elem2cgID.end(), make_pair( elem, cgID )); + ++cgID; + elem = elemIt->more() ? elemIt->next() : 0; + } + while ( elem && elem->GetEntityType() == elemType ); + + else if ( elemType == SMDSEntity_Polyhedra ) // POLYHEDRA + { + // to save polyhedrons after all + const SMDS_MeshInfo& meshInfo = myMesh->GetMeshInfo(); + if ( meshInfo.NbPolyhedrons() == meshInfo.NbElements() - cgID + 1 ) + break; // only polyhedrons remain + while ( elem && elem->GetEntityType() == elemType ) + elem = elemIt->more() ? elemIt->next() : 0; + continue; + } + + SMESH_Comment sectionName( cg_ElementTypeName( cgType )); + sectionName << " " << startID << " - " << cgID-1; + + if ( cg_section_write(_fn, iBase, iZone, sectionName.c_str(), cgType, startID, + cgID-1, /*nbndry=*/0, &elemData[0], &iSec) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + } + // Write polyhedral volumes + // ------------------------- + + if ( myMesh->GetMeshInfo().NbPolyhedrons() > 0 ) + { + // the polyhedron (NFACE_n) is described as a set of signed face IDs, + // so first we are to write all polygones (NGON_n) bounding polyhedrons + + vector< cgsize_t > faceData; + set< TPolyhedFace > faces; + set< TPolyhedFace >::iterator faceInSet; + vector faceNodesVec; + int nbPolygones = 0, faceID; + + SMDS_VolumeTool vol; + + elemData.clear(); + + int nbPolyhTreated = 0; + + TElem2cgIDMap * elem2cgID = 0; + TElem2cgIDMap & n2cgID = elem2cgIDByEntity[ SMDSEntity_Node ]; + + SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(); + while ( elemIt->more() ) + { + elem = elemIt->next(); + if ( elem->GetEntityType() == SMDSEntity_Polyhedra ) + { + ++nbPolyhTreated; + vol.Set( elem ); + vol.SetExternalNormal(); + const int nbFaces = vol.NbFaces(); + elemData.push_back( nbFaces ); + for ( int iF = 0; iF < nbFaces; ++iF ) + { + const int nbNodes = vol.NbFaceNodes( iF ); + const SMDS_MeshNode** faceNodes = vol.GetFaceNodes( iF ); + faceNodesVec.assign( faceNodes, faceNodes + nbNodes ); + if (( elem = myMesh->FindElement( faceNodesVec, SMDSAbs_Face, /*noMedium=*/false))) + { + // a face of the polyhedron is present in the mesh + faceID = cgnsID( elem, elem2cgIDByEntity[ elem->GetEntityType() ]); + } + else if ( vol.IsFreeFace( iF )) + { + // the face is not shared by volumes + faceID = cgID++; + ++nbPolygones; + faceData.push_back( nbNodes ); + for ( int i = 0; i < nbNodes; ++i ) + faceData.push_back( cgnsID( faceNodes[i], n2cgID )); + } + else + { + TPolyhedFace face( faceNodes, nbNodes, cgID ); + faceInSet = faces.insert( faces.end(), face ); + if ( faceInSet->_id == cgID ) // the face encounters for the 1st time + { + faceID = cgID++; + ++nbPolygones; + faceData.push_back( nbNodes ); + for ( int i = 0; i < nbNodes; ++i ) + faceData.push_back( cgnsID( faceNodes[i], n2cgID )); + } + else + { + // the face encounters for the 2nd time; we hope it won't encounter once more, + // for that we can erase it from the set of faces + faceID = -faceInSet->_id; + faces.erase( faceInSet ); + } + } + elemData.push_back( faceID ); + } + } + } + + if ( nbPolygones > 0 ) + { + if ( cg_section_write(_fn, iBase, iZone, "Faces of Polyhedrons", + CGNS_ENUMV( NGON_n ), cgID - nbPolygones, cgID-1, + /*nbndry=*/0, &faceData[0], &iSec) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + } + + if ( cg_section_write(_fn, iBase, iZone, "Polyhedrons", + CGNS_ENUMV( NFACE_n ), cgID, cgID+nbPolyhTreated-1, + /*nbndry=*/0, &elemData[0], &iSec) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + + if ( !myMesh->GetGroups().empty() ) + { + // store CGNS ids of polyhedrons + elem2cgID = &elem2cgIDByEntity[ SMDSEntity_Polyhedra ]; + elemIt = myMesh->elementsIterator(); + while ( elemIt->more() ) + { + elem = elemIt->next(); + if ( elem->GetEntityType() == SMDSEntity_Polyhedra ) + { + if ( elem->GetID() != cgID ) + elem2cgID->insert( elem2cgID->end(), make_pair( elem, cgID )); + ++cgID; + } + } + } + } // write polyhedral volumes + + + // Write groups as boundary conditions + // ------------------------------------ + + const set& groups = myMesh->GetGroups(); + set::const_iterator grpIt = groups.begin(); + set< string > groupNames; groupNames.insert(""); // to avoid duplicated and empty names + for ( ; grpIt != groups.end(); ++grpIt ) + { + const SMESHDS_GroupBase* group = *grpIt; + + // write BC location (default is Vertex) + CGNS_ENUMT( GridLocation_t ) location = CGNS_ENUMV( Vertex ); + if ( group->GetType() != SMDSAbs_Node ) + { + switch ( meshDim ) { + case 3: + switch ( group->GetType() ) { + case SMDSAbs_Volume: location = CGNS_ENUMV( FaceCenter ); break; // !!! + case SMDSAbs_Face: location = CGNS_ENUMV( FaceCenter ); break; // OK + case SMDSAbs_Edge: location = CGNS_ENUMV( EdgeCenter ); break; // OK + default:; + } + break; + case 2: + switch ( group->GetType() ) { + case SMDSAbs_Face: location = CGNS_ENUMV( FaceCenter ); break; // ??? + case SMDSAbs_Edge: location = CGNS_ENUMV( EdgeCenter ); break; // OK + default:; + } + break; + case 1: + location = CGNS_ENUMV( EdgeCenter ); break; // ??? + break; + } + } + + // try to extract type of boundary condition from the group name + string name = group->GetStoreName(); + CGNS_ENUMT( BCType_t ) bcType = getBCType( name ); + while ( !groupNames.insert( name ).second ) + name = (SMESH_Comment( "Group_") << groupNames.size()); + + // write IDs of elements + vector< cgsize_t > pnts; + pnts.reserve( group->Extent() ); + SMDS_ElemIteratorPtr elemIt = group->GetElements(); + while ( elemIt->more() ) + { + const SMDS_MeshElement* elem = elemIt->next(); + pnts.push_back( cgnsID( elem, elem2cgIDByEntity[ elem->GetEntityType() ])); + } + int iBC; + if ( cg_boco_write( _fn, iBase, iZone, name.c_str(), bcType, + CGNS_ENUMV( PointList ), pnts.size(), &pnts[0], &iBC) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true); + + // write BC location + if ( location != CGNS_ENUMV( Vertex )) + { + if ( cg_boco_gridlocation_write( _fn, iBase, iZone, iBC, location) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */false); + } + } + return DRS_OK; +} + +//================================================================================ +/*! + * \brief Constructor + */ +//================================================================================ + +DriverCGNS_Write::DriverCGNS_Write(): _fn(0) +{ +} + +//================================================================================ +/*! + * \brief Close the cgns file at destruction + */ +//================================================================================ + +DriverCGNS_Write::~DriverCGNS_Write() +{ + if ( _fn > 0 ) + cg_close( _fn ); +} diff --git a/src/DriverCGNS/DriverCGNS_Write.hxx b/src/DriverCGNS/DriverCGNS_Write.hxx new file mode 100644 index 000000000..fbe243524 --- /dev/null +++ b/src/DriverCGNS/DriverCGNS_Write.hxx @@ -0,0 +1,53 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : DriverCGNS_Write.hxx +// Created : Thu Jun 30 10:25:09 2011 +// Author : Edward AGAPOV (eap) + +#ifndef __DriverCGNS_Write_HXX__ +#define __DriverCGNS_Write_HXX__ + +#include "SMESH_DriverCGNS.hxx" + +#include "Driver_SMESHDS_Mesh.h" + +#include +#include + +/*! + * \brief Driver writinging a mesh into the CGNS file. + */ +class MESHDriverCGNS_EXPORT DriverCGNS_Write : public Driver_SMESHDS_Mesh +{ +public: + + DriverCGNS_Write(); + ~DriverCGNS_Write(); + + virtual Status Perform(); + +private: + + int _fn; //!< file index +}; + +#endif diff --git a/src/DriverCGNS/Makefile.am b/src/DriverCGNS/Makefile.am new file mode 100644 index 000000000..f7cdab3b2 --- /dev/null +++ b/src/DriverCGNS/Makefile.am @@ -0,0 +1,50 @@ +# Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# header files +salomeinclude_HEADERS = \ + DriverCGNS_Read.hxx \ + DriverCGNS_Write.hxx \ + SMESH_DriverCGNS.hxx + +# Libraries targets +lib_LTLIBRARIES = libMeshDriverCGNS.la +dist_libMeshDriverCGNS_la_SOURCES = \ + DriverCGNS_Read.cxx \ + DriverCGNS_Write.cxx + +# additionnal information to compil and link file +libMeshDriverCGNS_la_CPPFLAGS = \ + $(KERNEL_CXXFLAGS) \ + $(CAS_CPPFLAGS) \ + $(CGNS_INCLUDES) \ + $(VTK_INCLUDES) \ + $(BOOST_CPPFLAGS) \ + -I$(srcdir)/../Driver \ + -I$(srcdir)/../SMESHUtils \ + -I$(srcdir)/../SMDS \ + -I$(srcdir)/../SMESHDS + +libMeshDriverCGNS_la_LDFLAGS = \ + $(BOOST_LIBS) \ + $(CGNS_LIBS) \ + ../Driver/libMeshDriver.la + ../Driver/libSMESHUtils.la diff --git a/src/DriverCGNS/SMESH_DriverCGNS.hxx b/src/DriverCGNS/SMESH_DriverCGNS.hxx new file mode 100755 index 000000000..5f69ca644 --- /dev/null +++ b/src/DriverCGNS/SMESH_DriverCGNS.hxx @@ -0,0 +1,40 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESH_DriverCGNS.hxx +// Author : Alexander A. BORODIN +// Module : SMESH +// +#ifndef _SMESH_DriverCGNS_HXX_ +#define _SMESH_DriverCGNS_HXX_ + +#ifdef WNT + #if defined MESHDriverCGNS_EXPORTS || defined MeshDriverCGNS_EXPORTS + #define MESHDriverCGNS_EXPORT __declspec( dllexport ) + #else + #define MESHDriverCGNS_EXPORT __declspec( dllimport ) + #endif +#else + #define MESHDriverCGNS_EXPORT +#endif + +#endif