Salome HOME
Merge branch 'master' into pre/penta18
[modules/smesh.git] / src / DriverCGNS / DriverCGNS_Write.cxx
index 517a56f25afe361d8d45c93e042b7fd11926fcdc..4d79e0f7cca78c3a0b275f5c1ce2735b09e3eb5a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  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
@@ -6,7 +6,7 @@
 // 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.
+// 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
@@ -25,6 +25,7 @@
 
 #include "DriverCGNS_Write.hxx"
 
+#include "SMDS_IteratorOnIterators.hxx"
 #include "SMDS_MeshNode.hxx"
 #include "SMDS_VolumeTool.hxx"
 #include "SMESHDS_GroupBase.hxx"
@@ -81,6 +82,8 @@ namespace
         static int ids[] = { 0, 2, 1, 5, 4, 3 };
         interlaces[SMDSEntity_Quad_Triangle] = ids;
         cgTypes   [SMDSEntity_Quad_Triangle] = CGNS_ENUMV( TRI_6 );
+        interlaces[SMDSEntity_BiQuad_Triangle] = ids;
+        cgTypes   [SMDSEntity_BiQuad_Triangle] = CGNS_ENUMV( TRI_6 );
       }
       {
         static int ids[] = { 0, 3, 2, 1 };
@@ -127,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;
@@ -139,12 +147,13 @@ namespace
       }
       {
         static int ids[] = { 0,3,2,1,4,7,6,5,11,10,9,8,12,15,14,13,19,18,17,16,
-                             20, 24,23,22,21, 25};
+                             20, 24,23,22,21, 25, 26};
         interlaces[SMDSEntity_TriQuad_Hexa] = ids;
         cgTypes   [SMDSEntity_TriQuad_Hexa] = CGNS_ENUMV( HEXA_27 );
       }
       {
         cgTypes[SMDSEntity_Polygon]         = CGNS_ENUMV( NGON_n );
+        cgTypes[SMDSEntity_Quad_Polygon]    = CGNS_ENUMV( NGON_n );
         cgTypes[SMDSEntity_Polyhedra]       = CGNS_ENUMV( NFACE_n );
         cgTypes[SMDSEntity_Hexagonal_Prism] = CGNS_ENUMV( NFACE_n );
       }
@@ -169,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 )
         {
@@ -248,20 +257,20 @@ 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
@@ -328,6 +337,23 @@ Driver_Mesh::Status DriverCGNS_Write::Perform()
   int iSec;
   vector< cgsize_t > elemData;
   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 )
   {
@@ -341,9 +367,12 @@ Driver_Mesh::Status DriverCGNS_Write::Perform()
     startID = cgID;
 
     if ( interlace ) // STANDARD elements
+    {
+      int cgnsNbNodes; // get nb nodes by element type, that can be less that elem->NbNodes()
+      cg_npe( cgType, &cgnsNbNodes );
       do
       {
-        for ( int i = 0, nb = elem->NbNodes(); i < nb; ++i )
+        for ( int i = 0; i < cgnsNbNodes; ++i )
           elemData.push_back( cgnsID( elem->GetNode( interlace[i] ), n2cgID ));
         if ( elem->GetID() != cgID )
           elem2cgID.insert( elem2cgID.end(), make_pair( elem, cgID ));
@@ -351,7 +380,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform()
         elem = elemIt->more() ? elemIt->next() : 0;
       }
       while ( elem && elem->GetEntityType() == elemType );
-
+    }
     else if ( elemType == SMDSEntity_Polygon ) // POLYGONS
       do
       {
@@ -365,6 +394,21 @@ Driver_Mesh::Status DriverCGNS_Write::Perform()
       }
       while ( elem && elem->GetEntityType() == elemType );
 
+    else if ( elemType == SMDSEntity_Quad_Polygon ) // QUADRATIC POLYGONS
+      do // write as linear NGON_n
+      {
+        elemData.push_back( elem->NbNodes() );
+        interlace = & SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon,
+                                                          elem->NbNodes() )[0];
+        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_Polyhedra ||
               elemType == SMDSEntity_Hexagonal_Prism) // POLYHEDRA
     {
@@ -376,6 +420,15 @@ 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;
@@ -384,6 +437,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform()
                           cgID-1, /*nbndry=*/0, &elemData[0], &iSec) != CG_OK )
       return addMessage( cg_get_error(), /*fatal = */true );
   }
+
   // Write polyhedral volumes
   // -------------------------
 
@@ -513,21 +567,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;
       }
     }
@@ -535,9 +601,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() );
@@ -547,13 +620,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);
@@ -568,7 +643,7 @@ Driver_Mesh::Status DriverCGNS_Write::Perform()
  */
 //================================================================================
 
-DriverCGNS_Write::DriverCGNS_Write(): _fn(0)
+DriverCGNS_Write::DriverCGNS_Write(): _fn(0), _elementsByType( false )
 {
 }