1 // Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : DriverCGNS_Read.cxx
23 // Created : Thu Jun 30 10:33:31 2011
24 // Author : Edward AGAPOV (eap)
26 #include <utilities.h>
28 #include "DriverCGNS_Read.hxx"
30 #include "SMDS_MeshNode.hxx"
31 #include "SMESHDS_Group.hxx"
32 #include "SMESHDS_Mesh.hxx"
33 #include "SMESH_Comment.hxx"
34 #include "SMESH_TypeDefs.hxx"
36 #include <smIdType.hxx>
45 #if CGNS_VERSION < 3100
49 #define NB_ZONE_SIZE_VAL 9
50 #define CGNS_NAME_SIZE 33
51 #define CGNS_STRUCT_RANGE_SZ 6
57 //================================================================================
59 * \brief Data of a zone
64 smIdType _nodeIdShift; // nb nodes in previously read zones
65 smIdType _elemIdShift; // nb faces in previously read zones
66 smIdType _nbNodes, _nbElems;
68 int _sizeX, _sizeY, _sizeZ, _nbCells; // structured
69 cgsize_t _sizes[NB_ZONE_SIZE_VAL];
70 CGNS_ENUMT(ZoneType_t) _type;
71 map< int, int > _nodeReplacementMap;/* key: id of node to replace (in this zone),
72 value: id of node to replace by (in another zone)
73 id values include _nodeIdShift of the zones */
74 void SetSizeAndDim( cgsize_t* sizes, int meshDim )
77 memcpy( _sizes, sizes, NB_ZONE_SIZE_VAL*sizeof(cgsize_t));
79 _sizeY = _meshDim > 1 ? _sizes[1] : 0;
80 _sizeZ = _meshDim > 2 ? _sizes[2] : 0;
81 _nbCells = (_sizeX - 1) * ( _meshDim > 1 ? _sizeY : 1 ) * ( _meshDim > 2 ? _sizeZ : 1 );
83 bool IsStructured() const { return ( _type == CGNS_ENUMV( Structured )); }
84 int IndexSize() const { return IsStructured() ? _meshDim : 1; }
85 string ReadZonesConnection(int file, int base,
86 const map< string, TZoneData >& zonesByName,
88 void ReplaceNodes( cgsize_t* ids, int nbIds, int idShift = 0 ) const;
90 // Methods for a structured zone
92 int NodeID( int i, int j, int k = 1 ) const
94 return _nodeIdShift + (k-1)*_sizeX*_sizeY + (j-1)*_sizeX + i;
96 int NodeID( const gp_XYZ& ijk ) const
98 return NodeID( int(ijk.X()), int(ijk.Y()), int(ijk.Z()));
100 void CellNodes( int i, int j, int k, cgsize_t* ids ) const
102 ids[0] = NodeID( i , j , k );
103 ids[1] = NodeID( i , j+1, k );
104 ids[2] = NodeID( i+1, j+1, k );
105 ids[3] = NodeID( i+1, j , k );
106 ids[4] = NodeID( i , j , k+1);
107 ids[5] = NodeID( i , j+1, k+1);
108 ids[6] = NodeID( i+1, j+1, k+1);
109 ids[7] = NodeID( i+1, j , k+1);
111 void CellNodes( int i, int j, cgsize_t* ids ) const
113 ids[0] = NodeID( i , j );
114 ids[1] = NodeID( i , j+1 );
115 ids[2] = NodeID( i+1, j+1 );
116 ids[3] = NodeID( i+1, j );
118 void IFaceNodes( int i, int j, int k, cgsize_t* ids ) const // face perpendiculaire to X (3D)
120 ids[0] = NodeID( i, j, k );
121 ids[1] = ids[0] + _sizeX*( i==_sizeX ? 1 : _sizeY );
122 ids[2] = ids[0] + _sizeX*( _sizeY + 1 );
123 ids[3] = ids[0] + _sizeX*( i==_sizeX ? _sizeY : 1 );
125 void JFaceNodes( int i, int j, int k, cgsize_t* ids ) const
127 ids[0] = NodeID( i, j, k );
128 ids[1] = ids[0] + ( j==_sizeY ? _sizeX*_sizeY : 1);
129 ids[2] = ids[0] + _sizeX*_sizeY + 1;
130 ids[3] = ids[0] + ( j==_sizeY ? 1 : _sizeX*_sizeY);
132 void KFaceNodes( int i, int j, int k, cgsize_t* ids ) const
134 ids[0] = NodeID( i, j, k );
135 ids[1] = ids[0] + ( k==_sizeZ ? 1 : _sizeX);
136 ids[2] = ids[0] + _sizeX + 1;
137 ids[3] = ids[0] + ( k==_sizeZ ? _sizeX : 1);
139 void IEdgeNodes( int i, int j, int /*k*/, cgsize_t* ids ) const // edge perpendiculaire to X (2D)
141 ids[0] = NodeID( i, j, 0 );
142 ids[1] = ids[0] + _sizeX;
144 void JEdgeNodes( int i, int j, int /*k*/, cgsize_t* ids ) const
146 ids[0] = NodeID( i, j, 0 );
149 #define gpXYZ2IJK(METHOD) \
150 void METHOD( const gp_XYZ& ijk, cgsize_t* ids ) const { \
151 METHOD( int(ijk.X()), int(ijk.Y()), int(ijk.Z()), ids); \
153 gpXYZ2IJK( IFaceNodes )
154 gpXYZ2IJK( JFaceNodes )
155 gpXYZ2IJK( KFaceNodes )
156 gpXYZ2IJK( IEdgeNodes )
157 gpXYZ2IJK( JEdgeNodes )
160 //================================================================================
162 * \brief Iterator over nodes of the structired grid using FORTRAN multidimensional
165 class TPointRangeIterator
167 int _beg[3], _end[3], _cur[3], _dir[3], _dim;
170 TPointRangeIterator( const cgsize_t* range, int dim ):
171 _beg{0,0,0}, _end{0,0,0}, _cur{0,0,0}, _dir{0,0,0}, _dim(dim), _more(false)
173 for ( int i = 0; i < dim; ++i )
176 _end[i] = range[i+dim];
177 _dir[i] = _end[i] < _beg[i] ? -1 : 1;
180 if ( _end[i] - _beg[i] )
190 gp_XYZ res( _cur[0], _cur[1], _cur[2] );
191 for ( int i = 0; i < _dim; ++i )
194 if ( _cur[i]*_dir[i] < _end[i]*_dir[i] )
206 for ( int i = 0; i < _dim; ++i )
207 size *= _dir[i]*(_end[i]-_beg[i]);
210 gp_XYZ Begin() const { return gp_XYZ( _beg[0], _beg[1], _beg[2] ); }
211 //gp_XYZ End() const { return gp_XYZ( _end[0]-1, _end[1]-1, _end[2]-1 ); }
214 //================================================================================
216 * \brief Checks if the two arrays of node IDs describe nodes with equal coordinates
218 //================================================================================
220 bool isEqualNodes( const cgsize_t* nIds1, const cgsize_t* nIds2, size_t nbNodes,
225 SMESH_TNodeXYZ nn1[2], nn2[2];
226 nn1[0] = mesh->FindNode( nIds1[0] );
227 nn2[0] = mesh->FindNode( nIds2[0] );
228 if ( !nn1[0]._node || !nn2[0]._node )
230 double dist1 = ( nn1[0] - nn2[0] ).Modulus();
231 double dist2 = 0, tol = 1e-7;
234 nn1[1] = mesh->FindNode( nIds1[1] );
235 nn2[1] = mesh->FindNode( nIds2[1] );
236 if ( !nn1[1]._node || !nn2[1]._node )
238 dist2 = ( nn1[1] - nn2[1] ).Modulus();
239 tol = 1e-5 * ( nn1[0] - nn1[1] ).Modulus();
241 return ( dist1 < tol && dist2 < tol );
246 //================================================================================
248 * \brief Reads zone interface connectivity
249 * \param file - file to read
250 * \param base - base to read
251 * \param zone - zone to replace nodes in
252 * \param zonesByName - TZoneData by name
253 * \retval string - warning message
255 * see // http://www.grc.nasa.gov/WWW/cgns/CGNS_docs_current/sids/cnct.html
257 //================================================================================
259 string TZoneData::ReadZonesConnection( int file,
261 const map< string, TZoneData >& zonesByName,
266 char connectName[ CGNS_NAME_SIZE ], donorName [ CGNS_NAME_SIZE ];
268 // ----------------------------
269 // read zone 1 to 1 interfaces
270 // ----------------------------
271 if ( IsStructured() )
274 if ( cg_n1to1 ( file, base, _id, &nb1to1) == CG_OK )
276 cgsize_t range[CGNS_STRUCT_RANGE_SZ], donorRange[CGNS_STRUCT_RANGE_SZ];
277 int transform[3] = {0,0,0};
279 for ( int I = 1; I <= nb1to1; ++I )
281 if ( cg_1to1_read(file, base, _id, I, connectName,
282 donorName, range, donorRange, transform) == CG_OK )
284 map< string, TZoneData>::const_iterator n_z = zonesByName.find( donorName );
285 if ( n_z == zonesByName.end() )
286 continue; // donor zone not yet read
287 const TZoneData& zone2 = n_z->second;
289 // set up matrix to transform ijk of the zone to ijk of the zone2
291 for ( int i = 0; i < _meshDim; ++i )
294 int row = Abs(transform[i]);
296 int val = transform[i] > 0 ? +1 : -1;
300 // fill nodeReplacementMap
301 TPointRangeIterator rangeIt1( range, _meshDim );
302 TPointRangeIterator rangeIt2( donorRange, _meshDim );
303 gp_XYZ begin1 = rangeIt1.Begin(), begin2 = rangeIt2.Begin(), index1, index2;
304 if ( &zone2 == this )
306 // not to read twice the same interface with self
307 TPointRangeIterator rangeIt1bis( range, _meshDim );
308 if ( rangeIt1bis.More() )
310 index1 = rangeIt1bis.Next();
311 index2 = T * ( index1 - begin1 ) + begin2;
312 int node1 = NodeID( index1 );
313 int node2 = zone2.NodeID( index2 );
314 if ( _nodeReplacementMap.count( node2 ) &&
315 _nodeReplacementMap[ node2 ] == node1 )
316 continue; // this interface already read
319 // check if range and donorRange describe the same nodes
321 cgsize_t ids1[2], ids2[2], nbN = 0;
322 TPointRangeIterator rangeIt1bis( range, _meshDim );
323 index1 = rangeIt1bis.Next();
324 index2 = T * ( index1 - begin1 ) + begin2;
325 ids1[0] = NodeID( index1 );
326 ids2[0] = zone2.NodeID( index2 );
328 if ( rangeIt1bis.More() )
330 index1 = rangeIt1bis.Next();
331 index2 = T * ( index1 - begin1 ) + begin2;
332 ids1[1] = NodeID( index1 );
333 ids2[1] = zone2.NodeID( index2 );
336 if ( !isEqualNodes( &ids1[0], &ids2[0], nbN, mesh ))
339 while ( rangeIt1.More() )
341 index1 = rangeIt1.Next();
342 index2 = T * ( index1 - begin1 ) + begin2;
343 int node1 = NodeID( index1 );
344 int node2 = zone2.NodeID( index2 );
345 _nodeReplacementMap.insert( make_pair( node1, node2 ));
350 error = cg_get_error();
356 error = cg_get_error();
360 // ---------------------------------
361 // read general zone connectivities
362 // ---------------------------------
364 if ( cg_nconns( file, base, _id, &nbConn) == CG_OK )
366 cgsize_t nb, donorNb;
367 CGNS_ENUMT(GridLocation_t) location;
368 CGNS_ENUMT(GridConnectivityType_t) connectType;
369 CGNS_ENUMT(PointSetType_t) ptype, donorPtype;
370 CGNS_ENUMT(ZoneType_t) donorZonetype;
371 CGNS_ENUMT(DataType_t) donorDatatype;
373 for ( int I = 1; I <= nbConn; ++I )
375 if ( cg_conn_info(file, base, _id, I, connectName, &location, &connectType,
376 &ptype, &nb, donorName, &donorZonetype, &donorPtype,
377 &donorDatatype, &donorNb ) == CG_OK )
379 if ( location != CGNS_ENUMV( Vertex ))
380 continue; // we do not support cell-to-cell connectivity
381 if ( ptype != CGNS_ENUMV( PointList ) &&
382 ptype != CGNS_ENUMV( PointRange ))
384 if ( donorPtype != CGNS_ENUMV( PointList ) &&
385 donorPtype != CGNS_ENUMV( PointRange ))
388 map< string, TZoneData>::const_iterator n_z = zonesByName.find( donorName );
389 if ( n_z == zonesByName.end() )
390 continue; // donor zone not yet read
391 const TZoneData& zone2 = n_z->second;
393 vector< cgsize_t > ids( nb * IndexSize() );
394 vector< cgsize_t > donorIds( donorNb * zone2.IndexSize() );
395 if (cg_conn_read ( file, base, _id, I,
396 &ids[0], CGNS_ENUMV(Integer), &donorIds[0]) == CG_OK )
398 for ( int isThisZone = 0; isThisZone < 2; ++isThisZone )
400 const TZoneData& zone = isThisZone ? *this : zone2;
401 CGNS_ENUMT(PointSetType_t) type = isThisZone ? ptype : donorPtype;
402 vector< cgsize_t >& points = isThisZone ? ids : donorIds;
403 if ( type == CGNS_ENUMV( PointRange ))
405 TPointRangeIterator rangeIt( &points[0], zone._meshDim );
407 while ( rangeIt.More() )
408 points.push_back ( NodeID( rangeIt.Next() ));
410 else if ( zone.IsStructured() )
412 vector< cgsize_t > resIDs; resIDs.reserve( points.size() / IndexSize() );
413 for ( size_t i = 0; i < points.size(); i += IndexSize() )
414 resIDs.push_back( zone.NodeID( points[i+0], points[i+1], points[i+2] ));
415 resIDs.swap( points );
417 else if ( zone._nodeIdShift > 0 )
419 for ( size_t i = 0; i < points.size(); ++i )
420 points[i] += zone._nodeIdShift;
423 size_t nbN = std::min( ids.size(), donorIds.size());
424 if ( isEqualNodes( &ids[0], &donorIds[0], nbN, mesh ))
425 for ( size_t i = 0; i < nbN; ++i )
426 _nodeReplacementMap.insert( make_pair( ids[i], donorIds[i] ));
430 error = cg_get_error();
435 error = cg_get_error();
441 error = cg_get_error();
446 //================================================================================
448 * \brief Replaces node ids according to nodeReplacementMap to take into account
449 * connection of zones
451 //================================================================================
453 void TZoneData::ReplaceNodes( cgsize_t* ids, int nbIds, int idShift/* = 0*/ ) const
455 if ( !_nodeReplacementMap.empty() )
457 map< int, int >::const_iterator it, end = _nodeReplacementMap.end();
458 for ( int i = 0; i < nbIds; ++i )
459 if (( it = _nodeReplacementMap.find( ids[i] + idShift)) != end )
466 for ( int i = 0; i < nbIds; ++i )
470 //================================================================================
472 * \brief functions adding an element of a particular type
474 SMDS_MeshElement* add_0D(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
476 return mesh->Add0DElementWithID( ids[0], ID );
478 SMDS_MeshElement* add_BAR_2(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
480 return mesh->AddEdgeWithID( ids[0], ids[1], ID );
482 SMDS_MeshElement* add_BAR_3(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
484 return mesh->AddEdgeWithID( ids[0], ids[1], ids[2], ID );
486 SMDS_MeshElement* add_TRI_3(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
488 return mesh->AddFaceWithID( ids[0], ids[2], ids[1], ID );
490 SMDS_MeshElement* add_TRI_6(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
492 return mesh->AddFaceWithID( ids[0], ids[2], ids[1], ids[5], ids[4], ids[3], ID );
494 SMDS_MeshElement* add_QUAD_4(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
496 return mesh->AddFaceWithID( ids[0], ids[3], ids[2], ids[1], ID );
498 SMDS_MeshElement* add_QUAD_8(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
500 return mesh->AddFaceWithID( ids[0],ids[3],ids[2],ids[1],ids[7],ids[6],ids[5],ids[4], ID );
502 SMDS_MeshElement* add_QUAD_9(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
504 return mesh->AddFaceWithID( ids[0],ids[3],ids[2],ids[1],ids[7],ids[6],ids[5],ids[4],ids[8], ID);
506 SMDS_MeshElement* add_TETRA_4(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
508 return mesh->AddVolumeWithID( ids[0], ids[2], ids[1], ids[3], ID );
510 SMDS_MeshElement* add_TETRA_10(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
512 return mesh->AddVolumeWithID( ids[0],ids[2],ids[1],ids[3],ids[6],
513 ids[5],ids[4],ids[7],ids[9],ids[8], ID );
515 SMDS_MeshElement* add_PYRA_5(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
517 return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ID );
519 SMDS_MeshElement* add_PYRA_13(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
521 return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ids[8],ids[7],
522 ids[6],ids[5],ids[9],ids[12],ids[11],ids[10], ID );
524 SMDS_MeshElement* add_PENTA_6(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
526 return mesh->AddVolumeWithID( ids[0],ids[2],ids[1],ids[3],ids[5],ids[4], ID );
528 SMDS_MeshElement* add_PENTA_15(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
530 return mesh->AddVolumeWithID( ids[0],ids[2],ids[1],ids[3],ids[5],ids[4],ids[8],ids[7],
531 ids[6],ids[9],ids[11],ids[10],ids[14],ids[13],ids[12], ID );
533 SMDS_MeshElement* add_HEXA_8(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
535 return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ids[7],ids[6],ids[5], ID );
537 SMDS_MeshElement* add_HEXA_20(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
539 return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ids[7],ids[6],
540 ids[5],ids[11],ids[10],ids[9],ids[8],ids[12],ids[15],
541 ids[14],ids[13],ids[19],ids[18],ids[17],ids[16], ID );
543 SMDS_MeshElement* add_HEXA_27(cgsize_t* ids, SMESHDS_Mesh* mesh, int ID)
545 return mesh->AddVolumeWithID( ids[0],ids[3],ids[2],ids[1],ids[4],ids[7],ids[6],
546 ids[5],ids[11],ids[10],ids[9],ids[8],ids[12],ids[15],
547 ids[14],ids[13],ids[19],ids[18],ids[17],ids[16],
548 ids[20],ids[24],ids[23],ids[22],ids[21],ids[25],ids[26], ID );
550 SMDS_MeshElement* add_NGON(cgsize_t* ids, int nbNodes, SMESHDS_Mesh* mesh, int ID)
552 #if CGNS_VERSION < 4000
556 vector<smIdType> idVec( nbNodes );
557 for ( int i = 0; i < nbNodes; ++i )
558 idVec[ i ] = ToSmIdType( ids[ i ]);
559 return mesh->AddPolygonalFaceWithID( idVec, ToSmIdType(ID) );
562 typedef SMDS_MeshElement* (* PAddElemFun) (cgsize_t* ids, SMESHDS_Mesh* mesh, int ID);
564 //================================================================================
566 * \brief Return an array of functions each adding an element of a particular type
568 //================================================================================
570 PAddElemFun* getAddElemFunTable()
572 static vector< PAddElemFun > funVec;
573 if ( funVec.empty() )
575 funVec.resize( NofValidElementTypes, (PAddElemFun)0 );
576 funVec[ CGNS_ENUMV( NODE )] = add_0D ;
577 funVec[ CGNS_ENUMV( BAR_2 )] = add_BAR_2 ;
578 funVec[ CGNS_ENUMV( BAR_3 )] = add_BAR_3 ;
579 funVec[ CGNS_ENUMV( TRI_3 )] = add_TRI_3 ;
580 funVec[ CGNS_ENUMV( TRI_6 )] = add_TRI_6 ;
581 funVec[ CGNS_ENUMV( QUAD_4 )] = add_QUAD_4 ;
582 funVec[ CGNS_ENUMV( QUAD_8 )] = add_QUAD_8 ;
583 funVec[ CGNS_ENUMV( QUAD_9 )] = add_QUAD_9 ;
584 funVec[ CGNS_ENUMV( TETRA_4 )] = add_TETRA_4 ;
585 funVec[ CGNS_ENUMV( TETRA_10 )] = add_TETRA_10;
586 funVec[ CGNS_ENUMV( PYRA_5 )] = add_PYRA_5 ;
587 funVec[ CGNS_ENUMV( PYRA_13 )] = add_PYRA_13 ;
588 funVec[ CGNS_ENUMV( PYRA_14 )] = add_PYRA_13 ;
589 funVec[ CGNS_ENUMV( PENTA_6 )] = add_PENTA_6 ;
590 funVec[ CGNS_ENUMV( PENTA_15 )] = add_PENTA_15;
591 funVec[ CGNS_ENUMV( PENTA_18 )] = add_PENTA_15;
592 funVec[ CGNS_ENUMV( HEXA_8 )] = add_HEXA_8 ;
593 funVec[ CGNS_ENUMV( HEXA_20 )] = add_HEXA_20 ;
594 funVec[ CGNS_ENUMV( HEXA_27 )] = add_HEXA_27 ;
595 //funVec[ CGNS_ENUMV( NGON_n )] = add_NGON ;
600 //================================================================================
602 * \brief Finds an existing boundary element
604 //================================================================================
606 const SMDS_MeshElement* findElement(const cgsize_t* nodeIDs,
608 const SMESHDS_Mesh* mesh)
610 const SMDS_MeshNode* nn[4]; // look for quad4 or seg2
611 if (( nn[0] = mesh->FindNode( nodeIDs[0] )))
613 SMDSAbs_ElementType eType = nbNodes==4 ? SMDSAbs_Face : SMDSAbs_Edge;
614 SMDS_ElemIteratorPtr eIt = nn[0]->GetInverseElementIterator( eType );
616 for ( int i = 1; i < nbNodes; ++i )
617 nn[i] = mesh->FindNode( nodeIDs[i] );
618 while ( eIt->more() )
620 const SMDS_MeshElement* e = eIt->next();
621 if ( e->NbNodes() == nbNodes )
624 for ( int i = 1; i < nbNodes && elemOK; ++i )
625 elemOK = ( e->GetNodeIndex( nn[i] ) >= 0 );
636 //================================================================================
638 * \brief Perform reading a myMeshId-th mesh
640 //================================================================================
642 Driver_Mesh::Status DriverCGNS_Read::Perform()
644 MESSAGE("DriverCGNS_Read::Perform");
645 myErrorMessages.clear();
648 if (( aResult = open() ) != DRS_OK )
651 // read nb of meshes (CGNSBase_t)
652 if ( myMeshId < 0 || myMeshId >= GetNbMeshes(aResult))
653 return addMessage( SMESH_Comment("Invalid mesh index :") << myMeshId );
654 MESSAGE("NbMeshes: " << GetNbMeshes(aResult));
656 // read a name and a dimension of the mesh
657 const int cgnsBase = myMeshId + 1;
658 char meshName[CGNS_NAME_SIZE];
659 int meshDim, spaceDim;
660 if ( cg_base_read( _fn, cgnsBase, meshName, &meshDim, &spaceDim) != CG_OK )
661 return addMessage( cg_get_error() );
663 if ( spaceDim < 1 || spaceDim > 3 )
664 return addMessage( SMESH_Comment("Invalid space dimension: ") << spaceDim
665 << " in mesh '" << meshName << "'");
667 myMeshName = meshName;
668 MESSAGE("myMeshName: " << myMeshName);
671 // read nb of domains (Zone_t) in the mesh
673 if ( cg_nzones (_fn, cgnsBase, &nbZones) != CG_OK )
674 return addMessage( cg_get_error() );
677 return addMessage( SMESH_Comment("Empty mesh: '") << meshName << "'");
678 MESSAGE("nbZones: " << nbZones);
680 // read the domains (zones)
681 // ------------------------
682 map< string, TZoneData > zonesByName;
683 char name[CGNS_NAME_SIZE];
684 cgsize_t sizes[NB_ZONE_SIZE_VAL];
685 memset(sizes, 0, NB_ZONE_SIZE_VAL * sizeof(cgsize_t));
687 const SMDS_MeshInfo& meshInfo = myMesh->GetMeshInfo();
688 int groupID = myMesh->GetGroups().size();
690 for ( int iZone = 1; iZone <= nbZones; ++iZone )
692 // size and name of a zone
693 if ( cg_zone_read( _fn, cgnsBase, iZone, name, sizes) != CG_OK) {
694 addMessage( cg_get_error() );
697 TZoneData& zone = zonesByName[ name ];
699 zone._nodeIdShift = meshInfo.NbNodes();
700 zone._elemIdShift = meshInfo.NbElements();
701 zone.SetSizeAndDim( sizes, meshDim );
702 MESSAGE(" zone name: " << name);
704 // mesh type of the zone
705 if ( cg_zone_type ( _fn, cgnsBase, iZone, &zone._type) != CG_OK) {
706 addMessage( cg_get_error() );
710 switch ( zone._type )
712 case CGNS_ENUMV( Unstructured ):
713 MESSAGE(" zone type: unstructured");
715 case CGNS_ENUMV( Structured ):
716 MESSAGE(" zone type: structured");
718 case CGNS_ENUMV( ZoneTypeNull ):
719 addMessage( "Meshes with ZoneTypeNull are not supported");
721 case CGNS_ENUMV( ZoneTypeUserDefined ):
722 addMessage( "Meshes with ZoneTypeUserDefined are not supported");
725 addMessage( "Unknown ZoneType_t");
732 MESSAGE(" Read nodes");
733 if ( cg_ncoords( _fn, cgnsBase, iZone, &spaceDim) != CG_OK ) {
734 addMessage( cg_get_error() );
737 if ( spaceDim < 1 ) {
738 addMessage( SMESH_Comment("No coordinates defined in zone ")
739 << iZone << " of Mesh " << myMeshId );
744 MESSAGE(" Read coordinates");
745 cgsize_t rmin[3] = {1,1,1}; // range of nodes to read
746 cgsize_t rmax[3] = {1,1,1};
747 int nbNodes = rmax[0] = zone._sizes[0];
748 if ( zone.IsStructured())
749 for ( int i = 1; i < meshDim; ++i )
750 nbNodes *= rmax[i] = zone._sizes[i];
752 vector<double> coords[3];
753 for ( int c = 1; c <= spaceDim; ++c)
755 coords[c-1].resize( nbNodes );
757 CGNS_ENUMV( DataType_t ) type;
758 if ( cg_coord_info( _fn, cgnsBase, iZone, c, &type, name) != CG_OK ||
759 cg_coord_read( _fn, cgnsBase, iZone, name, CGNS_ENUMV(RealDouble),
760 rmin, rmax, (void*)&(coords[c-1][0])) != CG_OK)
762 addMessage( cg_get_error() );
767 if ( coords[ spaceDim-1 ].empty() )
768 continue; // there was an error while reading coordinates
770 // fill coords with zero if spaceDim < 3
771 for ( int c = 2; c <= 3; ++c)
772 if ( coords[ c-1 ].empty() )
773 coords[ c-1 ].resize( nbNodes, 0.0 );
776 MESSAGE(" create nodes");
778 for ( int i = 0; i < nbNodes; ++i )
779 myMesh->AddNodeWithID( coords[0][i], coords[1][i], coords[2][i], i+1+zone._nodeIdShift );
781 catch ( std::exception& exc ) // expect std::bad_alloc
783 addMessage( exc.what() );
787 // Read connectivity between zones. Nodes of the zone interface will be
788 // replaced within the zones read later
789 string err = zone.ReadZonesConnection( _fn, cgnsBase, zonesByName, myMesh );
796 MESSAGE(" read elements");
797 if ( zone.IsStructured())
799 int nbI = zone._sizeX - 1, nbJ = zone._sizeY - 1, nbK = zone._sizeZ - 1;
801 if ( meshDim > 2 && nbK > 0 )
803 for ( int k = 1; k <= nbK; ++k )
804 for ( int j = 1; j <= nbJ; ++j )
805 for ( int i = 1; i <= nbI; ++i )
807 zone.CellNodes( i, j, k, nID );
808 zone.ReplaceNodes( nID, 8 );
809 myMesh->AddVolumeWithID(nID[0],nID[1],nID[2],nID[3],nID[4],nID[5],nID[6],nID[7],
810 meshInfo.NbElements()+1);
813 else if ( meshDim > 1 && nbJ > 0 )
815 for ( int j = 1; j <= nbJ; ++j )
816 for ( int i = 1; i <= nbI; ++i )
818 zone.CellNodes( i, j, nID );
819 zone.ReplaceNodes( nID, 4 );
820 myMesh->AddFaceWithID(nID[0],nID[1],nID[2],nID[3], meshInfo.NbElements()+1);
823 else if ( meshDim > 0 && nbI > 0 )
825 nID[0] = zone.NodeID( 1, 0, 0 );
826 for ( int i = 1; i <= nbI; ++i, ++nID[0] )
829 zone.ReplaceNodes( nID, 2 );
830 myMesh->AddEdgeWithID(nID[0],nID[1], meshInfo.NbElements()+1);
836 // elements can be stored in different sections each dedicated to one element type
838 if ( cg_nsections( _fn, cgnsBase, iZone, &nbSections) != CG_OK)
840 addMessage( cg_get_error() );
843 PAddElemFun* addElemFuns = getAddElemFunTable(), curAddElemFun = 0;
844 int nbNotSuppElem = 0; // nb elements of not supported types
845 bool polyhedError = false; // error at polyhedron creation
849 MESSAGE(" read element data");
850 CGNS_ENUMT( ElementType_t ) elemType;
851 cgsize_t start, end; // range of ids of elements of a zone
852 cgsize_t eDataSize = 0;
853 int nbBnd, parent_flag;
854 for ( int iSec = 1; iSec <= nbSections; ++iSec )
856 MESSAGE(" section " << iSec << " of " << nbSections);
857 if ( cg_section_read( _fn, cgnsBase, iZone, iSec, name, &elemType,
858 &start, &end, &nbBnd, &parent_flag) != CG_OK ||
859 cg_ElementDataSize( _fn, cgnsBase, iZone, iSec, &eDataSize ) != CG_OK )
861 addMessage( cg_get_error() );
864 vector< cgsize_t > elemData( eDataSize ), polyOffset;
865 #if CGNS_VERSION >= 4000
866 if ( elemType == CGNS_ENUMV( MIXED ) ||
867 elemType == CGNS_ENUMV( NGON_n ) ||
868 elemType == CGNS_ENUMV( NFACE_n ))
870 polyOffset.resize( end - start + 2 );
871 if ( cg_poly_elements_read( _fn, cgnsBase, iZone, iSec,
872 elemData.data(), polyOffset.data(), NULL ) != CG_OK )
874 addMessage( cg_get_error() );
881 if ( cg_elements_read( _fn, cgnsBase, iZone, iSec, elemData.data(), NULL ) != CG_OK )
883 addMessage( cg_get_error() );
889 MESSAGE(" store elements");
890 int pos = 0, cgnsNbNodes = 0, elemID = start + zone._elemIdShift;
892 cg_npe( elemType, &cgnsNbNodes ); // get nb nodes by element type
893 curAddElemFun = addElemFuns[ elemType ];
894 SMDS_MeshElement* newElem = 0;
895 const SMDS_MeshElement* face;
896 vector<int> quantities;
897 vector<const SMDS_MeshNode*> nodes, faceNodes;
899 while ( pos < eDataSize )
901 CGNS_ENUMT( ElementType_t ) currentType = elemType;
902 if ( currentType == CGNS_ENUMV( MIXED )) {
903 //ElementConnectivity = Etype1, Node11, Node21, ... NodeN1,
904 // Etype2, Node12, Node22, ... NodeN2,
906 // EtypeM, Node1M, Node2M, ... NodeNM
907 currentType = (CGNS_ENUMT(ElementType_t)) elemData[ pos++ ];
908 cg_npe( currentType, &cgnsNbNodes );
909 curAddElemFun = addElemFuns[ currentType ];
911 if ( cgnsNbNodes < 1 ) // poly elements
913 if ( currentType == CGNS_ENUMV( NFACE_n )) // polyhedron
916 if ( polyOffset.empty() )
917 //ElementConnectivity = Nfaces1, Face11, Face21, ... FaceN1,
918 // Nfaces2, Face12, Face22, ... FaceN2,
920 // NfacesM, Face1M, Face2M, ... FaceNM
921 nbFaces = elemData[ pos++ ];
922 else // CGNS_VERSION >= 4000
923 // ElementConnectivity = Face11, Face21, ... FaceN1,
924 // Face12, Face22, ... FaceN2,
926 // Face1M, Face2M, ... FaceNM
927 nbFaces = polyOffset[ iElem + 1 ] - polyOffset[ iElem ];
929 quantities.resize( nbFaces ); quantities.back() = 0;
930 nodes.clear(); nodes.reserve( nbFaces * 4 );
931 for ( int iF = 0; iF < nbFaces; ++iF )
933 const int faceID = std::abs( elemData[ pos++ ]) + zone._elemIdShift;
934 if (( face = myMesh->FindElement( faceID )) && face->GetType() == SMDSAbs_Face )
936 const bool reverse = ( elemData[ pos-1 ] < 0 );
937 const int iQuad = face->IsQuadratic() ? 1 : 0;
938 SMDS_NodeIteratorPtr nIter = face->interlacedNodesIterator();
939 faceNodes.assign( SMDS_MeshElement::iterator( nIter ),
940 SMDS_MeshElement::iterator());
941 if ( iQuad && reverse )
942 nodes.push_back( faceNodes[0] );
944 nodes.insert( nodes.end(), faceNodes.rbegin(), faceNodes.rend() - iQuad );
946 nodes.insert( nodes.end(), faceNodes.begin(), faceNodes.end() );
948 quantities[ iF ] = face->NbNodes();
952 pos += nbFaces - iF - 1;
956 if ( quantities.back() )
958 myMesh->AddPolyhedralVolumeWithID( nodes, quantities, elemID );
961 else if ( currentType == CGNS_ENUMV( NGON_n )) // polygon
964 if ( polyOffset.empty() )
965 // ElementConnectivity = Nnodes1, Node11, Node21, ... NodeN1,
966 // Nnodes2, Node12, Node22, ... NodeN2,
968 // NnodesM, Node1M, Node2M, ... NodeNM
969 nbNodes = elemData[ pos ];
970 else // CGNS_VERSION >= 4000
971 // ElementConnectivity = Node11, Node21, ... NodeN1,
972 // Node12, Node22, ... NodeN2,
974 // Node1M, Node2M, ... NodeNM
975 nbNodes = polyOffset[ iElem + 1 ] - polyOffset[ iElem ];
977 zone.ReplaceNodes( &elemData[ pos + polyOffset.empty()], nbNodes, zone._nodeIdShift );
978 newElem = add_NGON( &elemData[ pos ], nbNodes, myMesh, elemID );
979 pos += nbNodes + polyOffset.empty();
982 else // standard elements
984 zone.ReplaceNodes( &elemData[pos], cgnsNbNodes, zone._nodeIdShift );
985 newElem = curAddElemFun( &elemData[pos], myMesh, elemID );
987 nbNotSuppElem += int( newElem && newElem->NbNodes() != cgnsNbNodes );
992 } // loop on elemData
993 } // loop on cgns sections
995 if ( nbNotSuppElem > 0 )
996 addMessage( SMESH_Comment(nbNotSuppElem) << " elements of not supported types"
997 << " have beem converted to close types");
999 addMessage( "Some polyhedral elements have been skipped due to internal(?) errors" );
1001 } // reading unstructured elements
1003 zone._nbNodes = meshInfo.NbNodes() - zone._nodeIdShift;
1004 zone._nbElems = meshInfo.NbElements() - zone._elemIdShift;
1006 // -------------------------------------------
1007 // Read Boundary Conditions into SMESH groups
1008 // -------------------------------------------
1010 MESSAGE(" read Boundary Conditions");
1012 if ( cg_nbocos( _fn, cgnsBase, iZone, &nbBC) == CG_OK )
1014 CGNS_ENUMT( BCType_t ) bcType;
1015 CGNS_ENUMT( PointSetType_t ) psType;
1016 CGNS_ENUMT( DataType_t ) normDataType;
1017 cgsize_t nbPnt, normFlag;
1018 int normIndex[3], nbDS;
1019 MESSAGE(" nbBC: " << nbBC);
1020 for ( int iBC = 1; iBC <= nbBC; ++iBC )
1022 MESSAGE(" iBC: " << iBC);
1023 if ( cg_boco_info( _fn, cgnsBase, iZone, iBC, name, &bcType, &psType,
1024 &nbPnt, normIndex, &normFlag, &normDataType, &nbDS ) != CG_OK )
1026 addMessage( cg_get_error() );
1029 MESSAGE(" iBC info OK: " << iBC);
1030 vector< cgsize_t > ids( nbPnt * zone.IndexSize() );
1031 CGNS_ENUMT( GridLocation_t ) location;
1032 if ( cg_boco_read( _fn, cgnsBase, iZone, iBC, &ids[0], NULL ) != CG_OK ||
1033 cg_boco_gridlocation_read( _fn, cgnsBase, iZone, iBC, &location) != CG_OK )
1035 addMessage( cg_get_error() );
1038 SMDSAbs_ElementType elemType = SMDSAbs_All;
1039 switch ( location ) {
1040 case CGNS_ENUMV( Vertex ): elemType = SMDSAbs_Node; break;
1041 case CGNS_ENUMV( FaceCenter ): elemType = SMDSAbs_Face; break;
1042 case CGNS_ENUMV( IFaceCenter ): elemType = SMDSAbs_Face; break;
1043 case CGNS_ENUMV( JFaceCenter ): elemType = SMDSAbs_Face; break;
1044 case CGNS_ENUMV( KFaceCenter ): elemType = SMDSAbs_Face; break;
1045 case CGNS_ENUMV( EdgeCenter ): elemType = SMDSAbs_Edge; break;
1048 SMESHDS_Group* group = new SMESHDS_Group ( groupID++, myMesh, elemType );
1049 myMesh->AddGroup( group );
1050 SMESH_Comment groupName( name ); groupName << " " << cg_BCTypeName( bcType );
1051 group->SetStoreName( groupName.c_str() );
1052 SMDS_MeshGroup& groupDS = group->SMDSGroup();
1054 if ( elemType == SMDSAbs_Node )
1056 if ( zone.IsStructured() )
1058 vector< cgsize_t > nodeIds;
1059 if ( psType == CGNS_ENUMV( PointRange ))
1061 // nodes are given as (ijkMin, ijkMax)
1062 TPointRangeIterator idIt( & ids[0], meshDim );
1063 nodeIds.reserve( idIt.Size() );
1064 while ( idIt.More() )
1065 nodeIds.push_back( zone.NodeID( idIt.Next() ));
1069 // nodes are given as (ijk1, ijk2, ..., ijkN)
1070 nodeIds.reserve( ids.size() / meshDim );
1071 for ( size_t i = 0; i < ids.size(); i += meshDim )
1072 nodeIds.push_back( zone.NodeID( ids[i], ids[i+1], ids[i+2] ));
1074 ids.swap( nodeIds );
1076 else if ( zone._nodeIdShift )
1078 for ( size_t i = 0; i < ids.size(); ++i )
1079 ids[i] += zone._nodeIdShift;
1081 zone.ReplaceNodes( &ids[0], ids.size() );
1083 for ( size_t i = 0; i < ids.size(); ++i )
1084 if ( const SMDS_MeshNode* n = myMesh->FindNode( ids[i] ))
1087 else // BC applied to elements
1089 if ( zone.IsStructured() )
1091 int axis = 0; // axis perpendiculaire to which boundary elements are oriented
1092 if ( (int) ids.size() >= meshDim * 2 )
1094 for ( ; axis < meshDim; ++axis )
1095 if ( ids[axis] - ids[axis+meshDim] == 0 )
1100 for ( ; axis < meshDim; ++axis )
1101 if ( normIndex[axis] != 0 )
1104 if ( axis == meshDim )
1106 addMessage( SMESH_Comment("Invalid NormalIndex in BC ") << name );
1109 const int nbElemNodesByDim[] = { 1, 2, 4, 8 };
1110 const int nbElemNodes = nbElemNodesByDim[ meshDim ];
1112 if ( psType == CGNS_ENUMV( PointRange ) ||
1113 psType == CGNS_ENUMV( ElementRange ))
1115 // elements are given as (ijkMin, ijkMax)
1116 typedef void (TZoneData::*PGetNodesFun)( const gp_XYZ& ijk, cgsize_t* ids ) const;
1117 PGetNodesFun getNodesFun = 0;
1118 if ( elemType == SMDSAbs_Face && meshDim == 3 )
1120 case 0: getNodesFun = & TZoneData::IFaceNodes; break;
1121 case 1: getNodesFun = & TZoneData::JFaceNodes; break;
1122 case 2: getNodesFun = & TZoneData::KFaceNodes; break;
1124 else if ( elemType == SMDSAbs_Edge && meshDim == 2 )
1126 case 0: getNodesFun = & TZoneData::IEdgeNodes; break;
1127 case 1: getNodesFun = & TZoneData::JEdgeNodes; break;
1131 addMessage( SMESH_Comment("Unsupported BC location in BC ") << name
1132 << " " << cg_GridLocationName( location )
1133 << " in " << meshDim << " mesh");
1136 TPointRangeIterator rangeIt( & ids[0], meshDim );
1137 vector< cgsize_t > elemNodeIds( rangeIt.Size() * nbElemNodes );
1138 for ( int i = 0; rangeIt.More(); i+= nbElemNodes )
1139 (zone.*getNodesFun)( rangeIt.Next(), &elemNodeIds[i] );
1141 ids.swap( elemNodeIds );
1145 // elements are given as (ijk1, ijk2, ..., ijkN)
1146 typedef void (TZoneData::*PGetNodesFun)( int i, int j, int k, cgsize_t* ids ) const;
1147 PGetNodesFun getNodesFun = 0;
1148 if ( elemType == SMDSAbs_Face )
1150 case 0: getNodesFun = & TZoneData::IFaceNodes; break;
1151 case 1: getNodesFun = & TZoneData::JFaceNodes; break;
1152 case 2: getNodesFun = & TZoneData::KFaceNodes; break;
1154 else if ( elemType == SMDSAbs_Edge && meshDim == 2 )
1156 case 0: getNodesFun = & TZoneData::IEdgeNodes; break;
1157 case 1: getNodesFun = & TZoneData::JEdgeNodes; break;
1161 addMessage( SMESH_Comment("Unsupported BC location in BC ") << name
1162 << " " << cg_GridLocationName( location )
1163 << " in " << meshDim << " mesh");
1166 vector< cgsize_t > elemNodeIds( ids.size()/meshDim * nbElemNodes );
1167 for ( size_t i = 0, j = 0; i < ids.size(); i += meshDim, j += nbElemNodes )
1168 (zone.*getNodesFun)( ids[i], ids[i+1], ids[i+2], &elemNodeIds[j] );
1170 ids.swap( elemNodeIds );
1172 zone.ReplaceNodes( &ids[0], ids.size() );
1174 PAddElemFun addElemFun = 0;
1175 switch ( meshDim ) {
1176 case 1: addElemFun = & add_BAR_2; break;
1177 case 2: addElemFun = & add_QUAD_4; break;
1178 case 3: addElemFun = & add_HEXA_8; break;
1180 smIdType elemID = meshInfo.NbElements();
1181 const SMDS_MeshElement* elem = 0;
1182 for ( size_t i = 0; i < ids.size(); i += nbElemNodes )
1184 if ( iZone == 1 || !( elem = findElement( &ids[i], nbElemNodes, myMesh )))
1185 elem = addElemFun( &ids[i], myMesh, ++elemID );
1186 groupDS.Add( elem );
1189 else // unstructured zone
1191 if ( zone._elemIdShift )
1192 for ( size_t i = 0; i < ids.size(); ++i )
1193 ids[i] += zone._elemIdShift;
1195 if ( psType == CGNS_ENUMV( PointRange ) && ids.size() == 2 )
1197 for ( cgsize_t i = ids[0]; i <= ids[1]; ++i )
1198 if ( const SMDS_MeshElement* e = myMesh->FindElement( i ))
1203 for ( size_t i = 0; i < ids.size(); ++i )
1204 if ( const SMDS_MeshElement* e = myMesh->FindElement( ids[i] ))
1208 } // end "BC applied to elements"
1210 // to have group type according to a real elem type
1211 group->SetType( groupDS.GetType() );
1213 } // loop on BCs of the zone
1215 else addMessage( cg_get_error() );
1218 MESSAGE(" read flow solutions");
1220 if ( cg_nsols( _fn, cgnsBase, iZone, &nsols) == CG_OK )
1222 MESSAGE(" nb flow solutions: " << nsols);
1224 else addMessage( cg_get_error() );
1226 MESSAGE(" read discrete data");
1228 if ( cg_ndiscrete( _fn, cgnsBase, iZone, &nbdiscrete) == CG_OK )
1230 MESSAGE(" nb discrete data: " << nbdiscrete);
1231 char nameDiscrete[CGNS_NAME_SIZE];
1232 for (int idisc = 1; idisc <= nbdiscrete; idisc++)
1234 if ( cg_discrete_read( _fn, cgnsBase, iZone, idisc, nameDiscrete) == CG_OK )
1236 MESSAGE(" discrete data #"<< idisc << " name: " << nameDiscrete);
1237 PointSetType_t ptset_type;
1239 if ( cg_discrete_ptset_info( _fn, cgnsBase, iZone, idisc, &ptset_type, &npnts) == CG_OK )
1241 MESSAGE(" discrete data #"<< idisc << " npnts: " << npnts);
1243 else addMessage( cg_get_error() );
1245 else addMessage( cg_get_error() );
1248 else addMessage( cg_get_error() );
1251 MESSAGE(" read subregions");
1253 if ( cg_nsubregs( _fn, cgnsBase, iZone, &nbSubrg) == CG_OK )
1255 MESSAGE(" nb subregions: " << nbSubrg);
1257 else addMessage( cg_get_error() );
1259 MESSAGE(" end zone");
1260 } // loop on the zones of a mesh
1262 MESSAGE("read families");
1264 if ( cg_nfamilies( _fn, cgnsBase, &nbFam) == CG_OK )
1266 MESSAGE("nb families: " << nbFam);
1268 else addMessage( cg_get_error() );
1272 // ------------------------------------------------------------------------
1273 // Make groups for multiple zones and remove free nodes at zone interfaces
1274 // ------------------------------------------------------------------------
1275 map< string, TZoneData >::iterator nameZoneIt = zonesByName.begin();
1276 for ( ; nameZoneIt != zonesByName.end(); ++nameZoneIt )
1278 MESSAGE("nameZone: " << nameZoneIt->first);
1279 TZoneData& zone = nameZoneIt->second;
1280 if ( zone._nbElems == 0 ) continue;
1281 if ( zone._nbElems == meshInfo.NbElements() ) break; // there is only one non-empty zone
1284 SMDSAbs_ElementType elemType = myMesh->GetElementType( zone._elemIdShift + 1,
1286 SMESHDS_Group* group = new SMESHDS_Group ( groupID++, myMesh, elemType );
1287 myMesh->AddGroup( group );
1288 group->SetStoreName( nameZoneIt->first.c_str() );
1289 SMDS_MeshGroup& groupDS = group->SMDSGroup();
1291 for ( int i = 1; i <= zone._nbElems; ++i )
1292 if ( const SMDS_MeshElement* e = myMesh->FindElement( i + zone._elemIdShift ))
1295 // remove free nodes
1296 map< int, int >::iterator nnRmKeepIt = zone._nodeReplacementMap.begin();
1297 for ( ; nnRmKeepIt != zone._nodeReplacementMap.end(); ++nnRmKeepIt )
1298 if ( const SMDS_MeshNode* n = myMesh->FindNode( nnRmKeepIt->first ))
1299 if ( n->NbInverseElements() == 0 )
1300 myMesh->RemoveFreeNode( n, (SMESHDS_SubMesh *)0, /*fromGroups=*/false );
1303 aResult = myErrorMessages.empty() ? DRS_OK : DRS_WARN_SKIP_ELEM;
1306 myMesh->CompactMesh();
1307 MESSAGE("end perform");
1311 //================================================================================
1313 * \brief Constructor
1315 //================================================================================
1317 DriverCGNS_Read::DriverCGNS_Read()
1321 //================================================================================
1323 * \brief Close the cgns file at destruction
1325 //================================================================================
1327 DriverCGNS_Read::~DriverCGNS_Read()
1333 //================================================================================
1335 * \brief Opens myFile
1337 //================================================================================
1339 Driver_Mesh::Status DriverCGNS_Read::open()
1345 int res = cg_open(myFile.c_str(), CG_MODE_READ, &_fn);
1347 int res = cg_open(myFile.c_str(), MODE_READ, &_fn);
1351 addMessage( cg_get_error(), /*fatal = */true );
1354 return _fn >= 0 ? DRS_OK : DRS_FAIL;
1357 //================================================================================
1359 * \brief Reads nb of meshes in myFile
1361 //================================================================================
1363 int DriverCGNS_Read::GetNbMeshes(Status& theStatus)
1365 if (( theStatus = open()) != DRS_OK )
1369 if(cg_nbases( _fn, &nbases) != CG_OK)
1370 theStatus = addMessage( cg_get_error(), /*fatal = */true );