1
6
7 #include "ReadCGNS.hpp"
8 #include "Internals.hpp"
9 #include "moab/Interface.hpp"
10 #include "moab/ReadUtilIface.hpp"
11 #include "moab/Range.hpp"
12 #include "moab/FileOptions.hpp"
13 #include "MBTagConventions.hpp"
14 #include "MBParallelConventions.h"
15 #include "moab/CN.hpp"
16
17 #include <cstdio>
18 #include <cassert>
19 #include <cerrno>
20 #include <map>
21 #include <set>
22
23 #include <iostream>
24 #include <cmath>
25
26 namespace moab
27 {
28
29 ReaderIface* ReadCGNS::factory( Interface* iface )
30 {
31 return new ReadCGNS( iface );
32 }
33
34 ReadCGNS::ReadCGNS( Interface* impl ) : fileName( NULL ), mesh_dim( 0 ), mbImpl( impl ), globalId( 0 ), boundary( 0 )
35 {
36 mbImpl->query_interface( readMeshIface );
37 }
38
39 ReadCGNS::~ReadCGNS()
40 {
41 if( readMeshIface )
42 {
43 mbImpl->release_interface( readMeshIface );
44 readMeshIface = 0;
45 }
46 }
47
48 ErrorCode ReadCGNS::read_tag_values( const char* ,
49 const char* ,
50 const FileOptions& ,
51 std::vector< int >& ,
52 const SubsetList* )
53 {
54 return MB_NOT_IMPLEMENTED;
55 }
56
57 ErrorCode ReadCGNS::load_file( const char* filename,
58 const EntityHandle* ,
59 const FileOptions& opts,
60 const ReaderIface::SubsetList* subset_list,
61 const Tag* file_id_tag )
62 {
63 int num_material_sets = 0;
64 const int* material_set_list = 0;
65
66 if( subset_list )
67 {
68 if( subset_list->tag_list_length > 1 && !strcmp( subset_list->tag_list[0].tag_name, MATERIAL_SET_TAG_NAME ) )
69 {
70 MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "CGNS supports subset read only by material ID" );
71 }
72 material_set_list = subset_list->tag_list[0].tag_values;
73 num_material_sets = subset_list->tag_list[0].num_tag_values;
74 }
75
76 ErrorCode result;
77
78 geomSets.clear();
79 globalId = mbImpl->globalId_tag();
80
81
82 std::set< int > blocks;
83 for( const int* mat_set_end = material_set_list + num_material_sets; material_set_list != mat_set_end;
84 ++material_set_list )
85 blocks.insert( *material_set_list );
86
87
88 std::map< long, EntityHandle > node_id_map;
89
90
91
92 fileName = filename;
93
94
95
96
97 result = process_options( opts );MB_CHK_SET_ERR( result, fileName << ": problem reading options" );
98
99
100 int filePtr = 0;
101
102 cg_open( filename, CG_MODE_READ, &filePtr );
103
104 if( filePtr <= 0 )
105 {
106 MB_SET_ERR( MB_FILE_DOES_NOT_EXIST, fileName << ": fopen returned error" );
107 }
108
109
110 long num_verts = 0, num_elems = 0, num_sets = 0;
111 int num_bases = 0, num_zones = 0, num_sections = 0;
112
113 char zoneName[128];
114 cgsize_t size[3];
115
116 mesh_dim = 3;
117
118
119 cg_nbases( filePtr, &num_bases );
120
121 if( num_bases > 1 )
122 {
123 MB_SET_ERR( MB_NOT_IMPLEMENTED, fileName << ": support for number of bases > 1 not implemented" );
124 }
125
126 for( int indexBase = 1; indexBase <= num_bases; ++indexBase )
127 {
128
129 cg_nzones( filePtr, indexBase, &num_zones );
130
131 if( num_zones > 1 )
132 {
133 MB_SET_ERR( MB_NOT_IMPLEMENTED, fileName << ": support for number of zones > 1 not implemented" );
134 }
135
136 for( int indexZone = 1; indexZone <= num_zones; ++indexZone )
137 {
138
139 cg_zone_read( filePtr, indexBase, indexZone, zoneName, size );
140
141
142 cg_nsections( filePtr, indexBase, indexZone, &num_sections );
143
144 num_verts = size[0];
145 num_elems = size[1];
146 num_sets = num_sections;
147
148 std::cout << "\nnumber of nodes = " << num_verts;
149 std::cout << "\nnumber of elems = " << num_elems;
150 std::cout << "\nnumber of parts = " << num_sets << std::endl;
151
152
153
154
155
156
157
158 std::vector< double* > coord_arrays;
159 EntityHandle handle = 0;
160 result = readMeshIface->get_node_coords( 3, num_verts, MB_START_ID, handle, coord_arrays );MB_CHK_SET_ERR( result, fileName << ": Trouble reading vertices" );
161
162
163 cgsize_t beginPos = 1, endPos = num_verts;
164
165
166 cg_coord_read( filePtr, indexBase, indexZone, "CoordinateX", RealDouble, &beginPos, &endPos,
167 coord_arrays[0] );
168 cg_coord_read( filePtr, indexBase, indexZone, "CoordinateY", RealDouble, &beginPos, &endPos,
169 coord_arrays[1] );
170 cg_coord_read( filePtr, indexBase, indexZone, "CoordinateZ", RealDouble, &beginPos, &endPos,
171 coord_arrays[2] );
172
173
174
175
176 double sumZcoord = 0.0;
177 double eps = 1.0e-12;
178 for( long i = 0; i < num_verts; ++i, ++handle )
179 {
180 int index = i + 1;
181
182 node_id_map.insert( std::pair< long, EntityHandle >( index, handle ) ).second;
183
184 sumZcoord += *( coord_arrays[2] + i );
185 }
186 if( std::abs( sumZcoord ) <= eps ) mesh_dim = 2;
187
188
189 std::vector< int > ids( num_verts );
190 std::vector< int >::iterator id_iter = ids.begin();
191 std::vector< EntityHandle > handles( num_verts );
192 std::vector< EntityHandle >::iterator h_iter = handles.begin();
193 for( std::map< long, EntityHandle >::iterator i = node_id_map.begin(); i != node_id_map.end();
194 ++i, ++id_iter, ++h_iter )
195 {
196 *id_iter = i->first;
197 *h_iter = i->second;
198 }
199
200 result = mbImpl->tag_set_data( globalId, &handles[0], num_verts, &ids[0] );
201 if( MB_SUCCESS != result ) return result;
202 if( file_id_tag )
203 {
204 result = mbImpl->tag_set_data( *file_id_tag, &handles[0], num_verts, &ids[0] );
205 if( MB_SUCCESS != result ) return result;
206 }
207 ids.clear();
208 handles.clear();
209
210
211
212
213 EntityType ent_type;
214
215 long section_offset = 0;
216
217
218
219 std::vector< int > volumeID( num_sections, 0 );
220
221 for( int section = 0; section < num_sections; ++section )
222 {
223 ElementType_t elemsType;
224 int iparent_flag, nbndry;
225 char sectionName[128];
226 int verts_per_elem;
227
228 int cgSection = section + 1;
229
230 cg_section_read( filePtr, indexBase, indexZone, cgSection, sectionName, &elemsType, &beginPos, &endPos,
231 &nbndry, &iparent_flag );
232
233 size_t section_size = endPos - beginPos + 1;
234
235
236
237 switch( elemsType )
238 {
239 case BAR_2:
240 ent_type = MBEDGE;
241 verts_per_elem = 2;
242 break;
243 case TRI_3:
244 ent_type = MBTRI;
245 verts_per_elem = 3;
246 if( mesh_dim == 2 ) volumeID[section] = 1;
247 break;
248 case QUAD_4:
249 ent_type = MBQUAD;
250 verts_per_elem = 4;
251 if( mesh_dim == 2 ) volumeID[section] = 1;
252 break;
253 case TETRA_4:
254 ent_type = MBTET;
255 verts_per_elem = 4;
256 if( mesh_dim == 3 ) volumeID[section] = 1;
257 break;
258 case PYRA_5:
259 ent_type = MBPYRAMID;
260 verts_per_elem = 5;
261 if( mesh_dim == 3 ) volumeID[section] = 1;
262 break;
263 case PENTA_6:
264 ent_type = MBPRISM;
265 verts_per_elem = 6;
266 if( mesh_dim == 3 ) volumeID[section] = 1;
267 break;
268 case HEXA_8:
269 ent_type = MBHEX;
270 verts_per_elem = 8;
271 if( mesh_dim == 3 ) volumeID[section] = 1;
272 break;
273 case MIXED:
274 ent_type = MBMAXTYPE;
275 verts_per_elem = 0;
276 break;
277 default:
278 MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type" );
279 }
280
281 if( elemsType == TETRA_4 || elemsType == PYRA_5 || elemsType == PENTA_6 || elemsType == HEXA_8 ||
282 elemsType == TRI_3 || elemsType == QUAD_4 || ( ( elemsType == BAR_2 ) && mesh_dim == 2 ) )
283 {
284
285
286 cgsize_t iparentdata;
287 cgsize_t connDataSize;
288
289
290 cg_ElementDataSize( filePtr, indexBase, indexZone, cgSection, &connDataSize );
291
292
293 std::vector< cgsize_t > elemNodes( connDataSize );
294
295 cg_elements_read( filePtr, indexBase, indexZone, cgSection, &elemNodes[0], &iparentdata );
296
297
298
299
300 create_elements( sectionName, file_id_tag, ent_type, verts_per_elem, section_offset, section_size,
301 elemNodes );
302 }
303 else if( elemsType == MIXED )
304 {
305
306
307 cgsize_t connDataSize;
308 cgsize_t iparentdata;
309
310 cg_ElementDataSize( filePtr, indexBase, indexZone, cgSection, &connDataSize );
311
312 std::vector< cgsize_t > elemNodes( connDataSize );
313
314 cg_elements_read( filePtr, indexBase, indexZone, cgSection, &elemNodes[0], &iparentdata );
315
316 std::vector< cgsize_t > elemsConn_EDGE;
317 std::vector< cgsize_t > elemsConn_TRI, elemsConn_QUAD;
318 std::vector< cgsize_t > elemsConn_TET, elemsConn_PYRA, elemsConn_PRISM, elemsConn_HEX;
319 cgsize_t count_EDGE, count_TRI, count_QUAD;
320 cgsize_t count_TET, count_PYRA, count_PRISM, count_HEX;
321
322
323
324 count_EDGE = count_TRI = count_QUAD = 0;
325 count_TET = count_PYRA = count_PRISM = count_HEX = 0;
326
327 int connIndex = 0;
328 for( int i = beginPos; i <= endPos; i++ )
329 {
330 elemsType = ElementType_t( elemNodes[connIndex] );
331
332
333 cg_npe( elemsType, &verts_per_elem );
334
335 switch( elemsType )
336 {
337 case BAR_2:
338 count_EDGE += 1;
339 break;
340 case TRI_3:
341 count_TRI += 1;
342 break;
343 case QUAD_4:
344 count_QUAD += 1;
345 break;
346 case TETRA_4:
347 count_TET += 1;
348 break;
349 case PYRA_5:
350 count_PYRA += 1;
351 break;
352 case PENTA_6:
353 count_PRISM += 1;
354 break;
355 case HEXA_8:
356 count_HEX += 1;
357 break;
358 default:
359 MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type" );
360 }
361
362 connIndex += ( verts_per_elem + 1 );
363 }
364
365 if( count_EDGE > 0 ) elemsConn_EDGE.resize( count_EDGE * 2 );
366 if( count_TRI > 0 ) elemsConn_TRI.resize( count_TRI * 3 );
367 if( count_QUAD > 0 ) elemsConn_QUAD.resize( count_QUAD * 4 );
368 if( count_TET > 0 ) elemsConn_TET.resize( count_TET * 4 );
369 if( count_PYRA > 0 ) elemsConn_PYRA.resize( count_PYRA * 5 );
370 if( count_PRISM > 0 ) elemsConn_PRISM.resize( count_PRISM * 6 );
371 if( count_HEX > 0 ) elemsConn_HEX.resize( count_HEX * 8 );
372
373
374
375 int idx_edge, idx_tri, idx_quad;
376 int idx_tet, idx_pyra, idx_prism, idx_hex;
377 idx_edge = idx_tri = idx_quad = 0;
378 idx_tet = idx_pyra = idx_prism = idx_hex = 0;
379
380 connIndex = 0;
381 for( int i = beginPos; i <= endPos; i++ )
382 {
383 elemsType = ElementType_t( elemNodes[connIndex] );
384
385
386 cg_npe( elemsType, &verts_per_elem );
387
388 switch( elemsType )
389 {
390 case BAR_2:
391 for( int j = 0; j < 2; ++j )
392 elemsConn_EDGE[idx_edge + j] = elemNodes[connIndex + j + 1];
393 idx_edge += 2;
394 break;
395 case TRI_3:
396 for( int j = 0; j < 3; ++j )
397 elemsConn_TRI[idx_tri + j] = elemNodes[connIndex + j + 1];
398 idx_tri += 3;
399 break;
400 case QUAD_4:
401 for( int j = 0; j < 4; ++j )
402 elemsConn_QUAD[idx_quad + j] = elemNodes[connIndex + j + 1];
403 idx_quad += 4;
404 break;
405 case TETRA_4:
406 for( int j = 0; j < 4; ++j )
407 elemsConn_TET[idx_tet + j] = elemNodes[connIndex + j + 1];
408 idx_tet += 4;
409 break;
410 case PYRA_5:
411 for( int j = 0; j < 5; ++j )
412 elemsConn_PYRA[idx_pyra + j] = elemNodes[connIndex + j + 1];
413 idx_pyra += 5;
414 break;
415 case PENTA_6:
416 for( int j = 0; j < 6; ++j )
417 elemsConn_PRISM[idx_prism + j] = elemNodes[connIndex + j + 1];
418 idx_prism += 6;
419 break;
420 case HEXA_8:
421 for( int j = 0; j < 8; ++j )
422 elemsConn_HEX[idx_hex + j] = elemNodes[connIndex + j + 1];
423 idx_hex += 8;
424 break;
425 default:
426 MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type" );
427 }
428
429 connIndex += ( verts_per_elem + 1 );
430 }
431
432
433
434
435 if( count_EDGE > 0 )
436 create_elements( sectionName, file_id_tag, MBEDGE, 2, section_offset, count_EDGE,
437 elemsConn_EDGE );
438
439 if( count_TRI > 0 )
440 create_elements( sectionName, file_id_tag, MBTRI, 3, section_offset, count_TRI, elemsConn_TRI );
441
442 if( count_QUAD > 0 )
443 create_elements( sectionName, file_id_tag, MBQUAD, 4, section_offset, count_QUAD,
444 elemsConn_QUAD );
445
446 if( count_TET > 0 )
447 create_elements( sectionName, file_id_tag, MBTET, 4, section_offset, count_TET, elemsConn_TET );
448
449 if( count_PYRA > 0 )
450 create_elements( sectionName, file_id_tag, MBPYRAMID, 5, section_offset, count_PYRA,
451 elemsConn_PYRA );
452
453 if( count_PRISM > 0 )
454 create_elements( sectionName, file_id_tag, MBPRISM, 6, section_offset, count_PRISM,
455 elemsConn_PRISM );
456
457 if( count_HEX > 0 )
458 create_elements( sectionName, file_id_tag, MBHEX, 8, section_offset, count_HEX, elemsConn_HEX );
459 }
460 }
461
462 cg_close( filePtr );
463
464 return result;
465 }
466 }
467
468 return MB_SUCCESS;
469 }
470
471 ErrorCode ReadCGNS::create_elements( char* sectionName,
472 const Tag* file_id_tag,
473 const EntityType& ent_type,
474 const int& verts_per_elem,
475 long& section_offset,
476 int elems_count,
477 const std::vector< cgsize_t >& elemsConn )
478 {
479 ErrorCode result;
480
481
482
483 EntityHandle* conn_array;
484 EntityHandle handle = 0;
485
486 result = readMeshIface->get_element_connect( elems_count, verts_per_elem, ent_type, 1, handle, conn_array );MB_CHK_SET_ERR( result, fileName << ": Trouble reading elements" );
487
488 if( sizeof( EntityHandle ) == sizeof( cgsize_t ) )
489 {
490 memcpy( conn_array, &elemsConn[0], elemsConn.size() * sizeof( EntityHandle ) );
491 }
492 else
493 {
494 std::vector< EntityHandle > elemsConnTwin( elemsConn.size(), 0 );
495 for( int i = 0; i < elemsConn.size(); i++ )
496 {
497 elemsConnTwin[i] = static_cast< EntityHandle >( elemsConn[i] );
498 }
499 memcpy( conn_array, &elemsConnTwin[0], elemsConnTwin.size() * sizeof( EntityHandle ) );
500 }
501
502
503 result = readMeshIface->update_adjacencies( handle, elems_count, verts_per_elem, conn_array );
504 if( MB_SUCCESS != result ) return result;
505
506
507
508
509 Range elements( handle, handle + elems_count - 1 );
510
511
512
513 std::vector< int > id_list( elems_count );
514
515
516 for( cgsize_t i = 0; i < elems_count; ++i )
517 id_list[i] = i + 1 + section_offset;
518 section_offset += elems_count;
519
520 create_sets( sectionName, file_id_tag, ent_type, elements, id_list, 0 );
521
522 return MB_SUCCESS;
523 }
524
525 ErrorCode ReadCGNS::create_sets( char* sectionName,
526 const Tag* file_id_tag,
527 EntityType ,
528 const Range& elements,
529 const std::vector< int >& set_ids,
530 int )
531 {
532 ErrorCode result;
533
534 result = mbImpl->tag_set_data( globalId, elements, &set_ids[0] );
535 if( MB_SUCCESS != result ) return result;
536
537 if( file_id_tag )
538 {
539 result = mbImpl->tag_set_data( *file_id_tag, elements, &set_ids[0] );
540 if( MB_SUCCESS != result ) return result;
541 }
542
543 EntityHandle set_handle;
544
545 Tag tag_handle;
546
547 const char* setName = sectionName;
548
549 mbImpl->tag_get_handle( setName, 1, MB_TYPE_INTEGER, tag_handle, MB_TAG_SPARSE | MB_TAG_CREAT );
550
551
552 result = mbImpl->create_meshset( MESHSET_SET, set_handle );MB_CHK_SET_ERR( result, fileName << ": Trouble creating set" );
553
554
555
556
557
558
559
560 result = mbImpl->add_entities( set_handle, elements );MB_CHK_SET_ERR( result, fileName << ": Trouble putting entities in set" );
561
562 return MB_SUCCESS;
563 }
564
565 ErrorCode ReadCGNS::process_options( const FileOptions& opts )
566 {
567
568 opts.mark_all_seen();
569
570 return MB_SUCCESS;
571 }
572
573 }