X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FDriverCGNS%2FDriverCGNS_Write.cxx;h=9320b826ac675f902802c7b482322e9e04635dcf;hp=f83fe915e283cb75693c039c6f63f3717a4f8488;hb=refs%2Ftags%2FV9_7_0b1;hpb=23d90107acec5e54ded86d9f309fe5cb42720b78 diff --git a/src/DriverCGNS/DriverCGNS_Write.cxx b/src/DriverCGNS/DriverCGNS_Write.cxx index f83fe915e..9320b826a 100644 --- a/src/DriverCGNS/DriverCGNS_Write.cxx +++ b/src/DriverCGNS/DriverCGNS_Write.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2021 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 @@ -25,6 +25,7 @@ #include "DriverCGNS_Write.hxx" +#include "SMDS_IteratorOnIterators.hxx" #include "SMDS_MeshNode.hxx" #include "SMDS_VolumeTool.hxx" #include "SMESHDS_GroupBase.hxx" @@ -129,6 +130,11 @@ namespace interlaces[SMDSEntity_Quad_Penta] = ids; cgTypes [SMDSEntity_Quad_Penta] = CGNS_ENUMV( PENTA_15 ); } + { + static int ids[] = { 0,2,1,3,5,4,8,7,6,9,11,10,14,13,12,15,16,17 }; // TODO: check CGNS ORDER + interlaces[SMDSEntity_BiQuad_Penta] = ids; + cgTypes [SMDSEntity_BiQuad_Penta] = CGNS_ENUMV( PENTA_18 ); + } { static int ids[] = { 0,3,2,1,4,7,6,5 }; interlaces[SMDSEntity_Hexa] = ids; @@ -172,7 +178,7 @@ namespace { for ( int t = 0; t < NofValidBCTypes; ++t ) { - CGNS_ENUMT( BCType_t ) type = CGNS_ENUMT( BCType_t)( t ); + CGNS_ENUMT( BCType_t ) type = CGNS_ENUMT( BCType_t )( t ); string typeName = cg_BCTypeName( type ); if ( typeName == &groupName[0] + bcBeg ) { @@ -195,17 +201,17 @@ namespace */ struct TPolyhedFace { - int _id; // id of NGON_n - vector< int > _nodes; // lowest node IDs used for sorting + smIdType _id; // id of NGON_n + vector< smIdType > _nodes; // lowest node IDs used for sorting - TPolyhedFace( const SMDS_MeshNode** nodes, const int nbNodes, int ID):_id(ID) + TPolyhedFace( const SMDS_MeshNode** nodes, const smIdType nbNodes, smIdType ID):_id(ID) { - set< int > ids; - for ( int i = 0; i < nbNodes; ++i ) + set< smIdType > ids; + for ( smIdType 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(); + set< smIdType >::iterator idIt = ids.begin(); for ( size_t j = 0; j < _nodes.size(); ++j, ++idIt ) _nodes[j] = *idIt; } @@ -227,6 +233,25 @@ namespace return ( e2id == elem2cgID.end() ? elem->GetID() : e2id->second ); } + //================================================================================ + /*! + * \brief save nb nodes of a polygon + */ + //================================================================================ + + void addPolySize( const cgsize_t nbNodes, + std::vector< cgsize_t >& elemData, + std::vector< cgsize_t >& polyOffset ) + { +#if CGNS_VERSION < 4100 + elemData.push_back( nbNodes ); + polyOffset.clear(); // just avoid warning: unused parameter +#else + polyOffset.push_back((cgsize_t) elemData.size() ); + (void)nbNodes; // avoid warning: unused parameter +#endif + } + } // namespace //================================================================================ @@ -242,6 +267,9 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() if ( !myMesh || myMesh->GetMeshInfo().NbElements() < 1 ) return addMessage( !myMesh ? "NULL mesh" : "Empty mesh (no elements)", /*fatal = */true ); + if ( Driver_Mesh::IsMeshTooLarge< cgsize_t >( myMesh, /*checkIDs =*/ false)) + return DRS_TOO_LARGE_MESH; + // 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 ) @@ -251,32 +279,34 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() // -------------- const int spaceDim = 3; - int meshDim = 1; - if ( myMesh->NbFaces() > 0 ) meshDim = 2; + 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) + 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)) + 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(); + smIdType 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 }; + cgsize_t size[9] = { FromSmIdType( myMesh->NbNodes() ), + FromSmIdType( 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 ) @@ -295,26 +325,26 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() vector< double > coords( myMesh->NbNodes() ); int iC; // X - SMDS_NodeIteratorPtr nIt = myMesh->nodesIterator( /*idInceasingOrder=*/true ); + SMDS_NodeIteratorPtr nIt = myMesh->nodesIterator(); 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 ); + nIt = myMesh->nodesIterator(); 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 ); + nIt = myMesh->nodesIterator(); 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 ); + nIt = myMesh->nodesIterator(); for ( int i = 0; nIt->more(); ++i ) { const SMDS_MeshElement* n = nIt->next(); @@ -329,8 +359,25 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() // write into a section all successive elements of one geom type int iSec; - vector< cgsize_t > elemData; + vector< cgsize_t > elemData, polyOffset; SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(); + vector< SMDS_ElemIteratorPtr > elemItVec; + if ( _elementsByType ) + { + // create an iterator returning all elements by type + for ( int type = SMDSEntity_Node + 1; type < SMDSEntity_Last; ++type ) + { + if ( type == SMDSEntity_Ball ) + continue; // not supported + elemIt = myMesh->elementEntityIterator( SMDSAbs_EntityType( type )); + if ( elemIt->more() ) + elemItVec.push_back( elemIt ); + } + typedef SMDS_IteratorOnIterators< const SMDS_MeshElement*, + vector< SMDS_ElemIteratorPtr > > TVecIterator; + elemIt.reset( new TVecIterator( elemItVec )); + } + const SMDS_MeshElement* elem = elemIt->next(); while ( elem ) { @@ -361,7 +408,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() else if ( elemType == SMDSEntity_Polygon ) // POLYGONS do { - elemData.push_back( elem->NbNodes() ); + addPolySize( elem->NbNodes(), elemData, polyOffset ); for ( int i = 0, nb = elem->NbNodes(); i < nb; ++i ) elemData.push_back( cgnsID( elem->GetNode(i), n2cgID )); if ( elem->GetID() != cgID ) @@ -374,7 +421,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() else if ( elemType == SMDSEntity_Quad_Polygon ) // QUADRATIC POLYGONS do // write as linear NGON_n { - elemData.push_back( elem->NbNodes() ); + addPolySize( elem->NbNodes(), elemData, polyOffset ); interlace = & SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, elem->NbNodes() )[0]; for ( int i = 0, nb = elem->NbNodes(); i < nb; ++i ) @@ -397,14 +444,38 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() elem = elemIt->more() ? elemIt->next() : 0; continue; } + else // skip NOT SUPPORTED elements + { + while ( elemIt->more() ) + { + elem = elemIt->next(); + if ( elem->GetEntityType() != elemType ) + break; + } + } 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 ); + +#if CGNS_VERSION >= 4000 + if ( !polyOffset.empty() ) + { + polyOffset.push_back((cgsize_t) elemData.size() ); + if ( cg_poly_section_write(_fn, iBase, iZone, sectionName.c_str(), cgType, startID, + cgID-1, /*nbndry=*/0, + elemData.data(), polyOffset.data(), &iSec) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + } + else +#endif + { + if ( cg_section_write(_fn, iBase, iZone, sectionName.c_str(), cgType, startID, + cgID-1, /*nbndry=*/0, elemData.data(), &iSec) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + } } + // Write polyhedral volumes // ------------------------- @@ -417,11 +488,13 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() set< TPolyhedFace > faces; set< TPolyhedFace >::iterator faceInSet; vector faceNodesVec; + vector< cgsize_t > faceOffset; int nbPolygones = 0, faceID; SMDS_VolumeTool vol; elemData.clear(); + polyOffset.clear(); int nbPolyhTreated = 0; @@ -440,7 +513,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() vol.Set( elem ); vol.SetExternalNormal(); const int nbFaces = vol.NbFaces(); - elemData.push_back( nbFaces ); + addPolySize( nbFaces, elemData, polyOffset ); for ( int iF = 0; iF < nbFaces; ++iF ) { const int nbNodes = vol.NbFaceNodes( iF ); @@ -456,7 +529,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() // the face is not shared by volumes faceID = cgID++; ++nbPolygones; - faceData.push_back( nbNodes ); + addPolySize( nbNodes, faceData, faceOffset ); for ( int i = 0; i < nbNodes; ++i ) faceData.push_back( cgnsID( faceNodes[i], n2cgID )); } @@ -468,7 +541,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() { faceID = cgID++; ++nbPolygones; - faceData.push_back( nbNodes ); + addPolySize( nbNodes, faceData, faceOffset ); for ( int i = 0; i < nbNodes; ++i ) faceData.push_back( cgnsID( faceNodes[i], n2cgID )); } @@ -485,18 +558,35 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() } } +#if CGNS_VERSION >= 4000 + if ( nbPolygones > 0 ) + { + faceOffset.push_back((cgsize_t) faceData.size() ); + if ( cg_poly_section_write(_fn, iBase, iZone, "Faces of Polyhedrons", CGNS_ENUMV( NGON_n ), + cgID - nbPolygones, cgID-1, /*nbndry=*/0, + faceData.data(), faceOffset.data(), &iSec) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); + } + + polyOffset.push_back((cgsize_t) elemData.size() ); + if ( cg_poly_section_write(_fn, iBase, iZone, "Polyhedrons", + CGNS_ENUMV( NFACE_n ), cgID, cgID+nbPolyhTreated-1, + /*nbndry=*/0, &elemData[0], polyOffset.data(), &iSec) != CG_OK ) + return addMessage( cg_get_error(), /*fatal = */true ); +#else 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 ) + 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 ) + + 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 ); +#endif if ( !myMesh->GetGroups().empty() ) { @@ -534,21 +624,33 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() 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 +#if CGNS_VERSION > 3130 + case SMDSAbs_Volume: location = CGNS_ENUMV( CellCenter ); break; +#else + case SMDSAbs_Volume: location = CGNS_ENUMV( FaceCenter ); break; +#endif + case SMDSAbs_Face: location = CGNS_ENUMV( FaceCenter ); break; + case SMDSAbs_Edge: location = CGNS_ENUMV( EdgeCenter ); break; default:; } break; case 2: switch ( group->GetType() ) { - case SMDSAbs_Face: location = CGNS_ENUMV( FaceCenter ); break; // ??? - case SMDSAbs_Edge: location = CGNS_ENUMV( EdgeCenter ); break; // OK +#if CGNS_VERSION > 3130 + case SMDSAbs_Face: location = CGNS_ENUMV( CellCenter ); break; +#else + case SMDSAbs_Face: location = CGNS_ENUMV( FaceCenter ); break; +#endif + case SMDSAbs_Edge: location = CGNS_ENUMV( EdgeCenter ); break; default:; } break; case 1: - location = CGNS_ENUMV( EdgeCenter ); break; // ??? +#if CGNS_VERSION > 3130 + location = CGNS_ENUMV( CellCenter ); break; +#else + location = CGNS_ENUMV( EdgeCenter ); break; +#endif break; } } @@ -556,9 +658,16 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() // 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()); - + if ( !groupNames.insert( name ).second ) // assure name uniqueness + { + int index = 1; + string newName; + do { + newName = SMESH_Comment( name ) << "_" << index++; + } + while ( !groupNames.insert( newName ).second ); + name = newName; + } // write IDs of elements vector< cgsize_t > pnts; pnts.reserve( group->Extent() ); @@ -568,13 +677,15 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() const SMDS_MeshElement* elem = elemIt->next(); pnts.push_back( cgnsID( elem, elem2cgIDByEntity[ elem->GetEntityType() ])); } + if ( pnts.size() == 0 ) + continue; // can't store empty group 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 ( location != CGNS_ENUMV( Vertex ) || meshDim == 1 ) { if ( cg_boco_gridlocation_write( _fn, iBase, iZone, iBC, location) != CG_OK ) return addMessage( cg_get_error(), /*fatal = */false); @@ -589,7 +700,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform() */ //================================================================================ -DriverCGNS_Write::DriverCGNS_Write(): _fn(0) +DriverCGNS_Write::DriverCGNS_Write(): _fn(0), _elementsByType( false ) { }