![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /**
00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003 * storing and accessing finite element mesh data.
00004 *
00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract
00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007 * retains certain rights in this software.
00008 *
00009 * This library is free software; you can redistribute it and/or
00010 * modify it under the terms of the GNU Lesser General Public
00011 * License as published by the Free Software Foundation; either
00012 * version 2.1 of the License, or (at your option) any later version.
00013 *
00014 */
00015
00016 #ifdef WIN32
00017 #ifdef _DEBUG
00018 // turn off warnings that say they debugging identifier has been truncated
00019 // this warning comes up when using some STL containers
00020 #pragma warning( disable : 4786 )
00021 #endif
00022 #endif
00023
00024 #include "WriteTemplate.hpp"
00025
00026 #include
00027 #include
00028 #include
00029 #include
00030 #include
00031 #include
00032 #include
00033 #include
00034
00035 #include "moab/Interface.hpp"
00036 #include "moab/Range.hpp"
00037 #include "moab/CN.hpp"
00038 #include
00039 #include "Internals.hpp"
00040 #include "ExoIIUtil.hpp"
00041 #include "MBTagConventions.hpp"
00042 #include "moab/WriteUtilIface.hpp"
00043
00044 namespace moab
00045 {
00046
00047 #define INS_ID( stringvar, prefix, id ) sprintf( stringvar, prefix, id )
00048
00049 WriterIface* WriteTemplate::factory( Interface* iface )
00050 {
00051 return new WriteTemplate( iface );
00052 }
00053
00054 WriteTemplate::WriteTemplate( Interface* impl ) : mbImpl( impl )
00055 {
00056 assert( impl != NULL );
00057
00058 impl->query_interface( mWriteIface );
00059
00060 // Initialize in case tag_get_handle fails below
00061 //! Get and cache predefined tag handles
00062 int negone = -1;
00063 impl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mMaterialSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00064 &negone );
00065
00066 impl->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mDirichletSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00067 &negone );
00068
00069 impl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mNeumannSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00070 &negone );
00071
00072 mGlobalIdTag = impl->globalId_tag();
00073
00074 impl->tag_get_handle( "WriteTemplate element mark", 1, MB_TYPE_BIT, mEntityMark, MB_TAG_CREAT );
00075 }
00076
00077 WriteTemplate::~WriteTemplate()
00078 {
00079 mbImpl->release_interface( mWriteIface );
00080 mbImpl->tag_delete( mEntityMark );
00081 }
00082
00083 void WriteTemplate::reset_matset( std::vector< WriteTemplate::MaterialSetData >& matset_info )
00084 {
00085 std::vector< WriteTemplate::MaterialSetData >::iterator iter;
00086
00087 for( iter = matset_info.begin(); iter != matset_info.end(); ++iter )
00088 delete( *iter ).elements;
00089 }
00090
00091 ErrorCode WriteTemplate::write_file( const char* file_name,
00092 const bool /* overwrite (commented out to remove warning) */,
00093 const FileOptions& /*opts*/,
00094 const EntityHandle* ent_handles,
00095 const int num_sets,
00096 const std::vector< std::string >& /* qa_list */,
00097 const Tag* /* tag_list */,
00098 int /* num_tags */,
00099 int /* export_dimension */ )
00100 {
00101 assert( 0 != mMaterialSetTag && 0 != mNeumannSetTag && 0 != mDirichletSetTag );
00102
00103 // Check the file name
00104 if( NULL == strstr( file_name, ".template" ) ) return MB_FAILURE;
00105
00106 std::vector< EntityHandle > matsets, dirsets, neusets;
00107
00108 fileName = file_name;
00109
00110 // Separate into material sets, dirichlet sets, neumann sets
00111
00112 if( num_sets == 0 )
00113 {
00114 // Default to all defined sets
00115 Range this_range;
00116 mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mMaterialSetTag, NULL, 1, this_range );
00117 std::copy( this_range.begin(), this_range.end(), std::back_inserter( matsets ) );
00118 this_range.clear();
00119 mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mDirichletSetTag, NULL, 1, this_range );
00120 std::copy( this_range.begin(), this_range.end(), std::back_inserter( dirsets ) );
00121 this_range.clear();
00122 mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mNeumannSetTag, NULL, 1, this_range );
00123 std::copy( this_range.begin(), this_range.end(), std::back_inserter( neusets ) );
00124 }
00125 else
00126 {
00127 int dummy;
00128 for( const EntityHandle* iter = ent_handles; iter < ent_handles + num_sets; ++iter )
00129 {
00130 if( MB_SUCCESS == mbImpl->tag_get_data( mMaterialSetTag, &( *iter ), 1, &dummy ) )
00131 matsets.push_back( *iter );
00132 else if( MB_SUCCESS == mbImpl->tag_get_data( mDirichletSetTag, &( *iter ), 1, &dummy ) )
00133 dirsets.push_back( *iter );
00134 else if( MB_SUCCESS == mbImpl->tag_get_data( mNeumannSetTag, &( *iter ), 1, &dummy ) )
00135 neusets.push_back( *iter );
00136 }
00137 }
00138
00139 // If there is nothing to write just return.
00140 if( matsets.empty() && dirsets.empty() && neusets.empty() ) return MB_FILE_WRITE_ERROR;
00141
00142 std::vector< WriteTemplate::MaterialSetData > matset_info;
00143 std::vector< WriteTemplate::DirichletSetData > dirset_info;
00144 std::vector< WriteTemplate::NeumannSetData > neuset_info;
00145
00146 MeshInfo mesh_info;
00147
00148 matset_info.clear();
00149 if( gather_mesh_information( mesh_info, matset_info, neuset_info, dirset_info, matsets, neusets, dirsets ) !=
00150 MB_SUCCESS )
00151 {
00152 reset_matset( matset_info );
00153 return MB_FAILURE;
00154 }
00155
00156 // Try to open the file after gather mesh info succeeds
00157 if( /* Test for file open failure */ false )
00158 {
00159 reset_matset( matset_info );
00160 return MB_FAILURE;
00161 }
00162
00163 if( initialize_file( mesh_info ) != MB_SUCCESS )
00164 {
00165 reset_matset( matset_info );
00166 return MB_FAILURE;
00167 }
00168
00169 if( write_nodes( mesh_info.num_nodes, mesh_info.nodes, mesh_info.num_dim ) != MB_SUCCESS )
00170 {
00171 reset_matset( matset_info );
00172 return MB_FAILURE;
00173 }
00174
00175 if( write_matsets( mesh_info, matset_info, neuset_info ) )
00176 {
00177 reset_matset( matset_info );
00178 return MB_FAILURE;
00179 }
00180
00181 return MB_SUCCESS;
00182 }
00183
00184 ErrorCode WriteTemplate::gather_mesh_information( MeshInfo& mesh_info,
00185 std::vector< WriteTemplate::MaterialSetData >& matset_info,
00186 std::vector< WriteTemplate::NeumannSetData >& neuset_info,
00187 std::vector< WriteTemplate::DirichletSetData >& dirset_info,
00188 std::vector< EntityHandle >& matsets,
00189 std::vector< EntityHandle >& neusets,
00190 std::vector< EntityHandle >& dirsets )
00191 {
00192 std::vector< EntityHandle >::iterator vector_iter, end_vector_iter;
00193
00194 mesh_info.num_nodes = 0;
00195 mesh_info.num_elements = 0;
00196 mesh_info.num_matsets = 0;
00197
00198 int id = 0;
00199
00200 vector_iter = matsets.begin();
00201 end_vector_iter = matsets.end();
00202
00203 mesh_info.num_matsets = matsets.size();
00204
00205 std::vector< EntityHandle > parent_meshsets;
00206
00207 // Clean out the bits for the element mark
00208 mbImpl->tag_delete( mEntityMark );
00209 mbImpl->tag_get_handle( "WriteTemplate element mark", 1, MB_TYPE_BIT, mEntityMark, MB_TAG_CREAT );
00210
00211 int highest_dimension_of_element_matsets = 0;
00212
00213 for( vector_iter = matsets.begin(); vector_iter != matsets.end(); ++vector_iter )
00214 {
00215 WriteTemplate::MaterialSetData matset_data;
00216 matset_data.elements = new Range;
00217
00218 // For the purpose of qa records, get the parents of these matsets
00219 if( mbImpl->get_parent_meshsets( *vector_iter, parent_meshsets ) != MB_SUCCESS ) return MB_FAILURE;
00220
00221 // Get all Entity Handles in the mesh set
00222 Range dummy_range;
00223 mbImpl->get_entities_by_handle( *vector_iter, dummy_range, true );
00224
00225 // Find the dimension of the last entity in this range
00226 Range::iterator entity_iter = dummy_range.end();
00227 --entity_iter;
00228 int this_dim = CN::Dimension( TYPE_FROM_HANDLE( *entity_iter ) );
00229 entity_iter = dummy_range.begin();
00230 while( entity_iter != dummy_range.end() && CN::Dimension( TYPE_FROM_HANDLE( *entity_iter ) ) != this_dim )
00231 ++entity_iter;
00232
00233 if( entity_iter != dummy_range.end() )
00234 std::copy( entity_iter, dummy_range.end(), range_inserter( *( matset_data.elements ) ) );
00235
00236 assert( matset_data.elements->begin() == matset_data.elements->end() ||
00237 CN::Dimension( TYPE_FROM_HANDLE( *( matset_data.elements->begin() ) ) ) == this_dim );
00238
00239 // Get the matset's id
00240 if( mbImpl->tag_get_data( mMaterialSetTag, &( *vector_iter ), 1, &id ) != MB_SUCCESS )
00241 {
00242 MB_SET_ERR( MB_FAILURE, "Couldn't get matset id from a tag for an element matset" );
00243 }
00244
00245 matset_data.id = id;
00246 matset_data.number_attributes = 0;
00247
00248 // Iterate through all the elements in the meshset
00249 Range::iterator elem_range_iter, end_elem_range_iter;
00250 elem_range_iter = matset_data.elements->begin();
00251 end_elem_range_iter = matset_data.elements->end();
00252
00253 // Get the entity type for this matset, verifying that it's the same for all elements
00254 // THIS ASSUMES HANDLES SORT BY TYPE!!!
00255 EntityType entity_type = TYPE_FROM_HANDLE( *elem_range_iter );
00256 --end_elem_range_iter;
00257 if( entity_type != TYPE_FROM_HANDLE( *( end_elem_range_iter++ ) ) )
00258 {
00259 MB_SET_ERR( MB_FAILURE, "Entities in matset " << id << " not of common type" );
00260 }
00261
00262 int dimension = CN::Dimension( entity_type );
00263
00264 if( dimension > highest_dimension_of_element_matsets ) highest_dimension_of_element_matsets = dimension;
00265
00266 matset_data.moab_type = mbImpl->type_from_handle( *( matset_data.elements->begin() ) );
00267 if( MBMAXTYPE == matset_data.moab_type ) return MB_FAILURE;
00268
00269 std::vector< EntityHandle > tmp_conn;
00270 mbImpl->get_connectivity( &( *( matset_data.elements->begin() ) ), 1, tmp_conn );
00271 matset_data.element_type =
00272 ExoIIUtil::get_element_type_from_num_verts( tmp_conn.size(), entity_type, dimension );
00273
00274 if( matset_data.element_type == EXOII_MAX_ELEM_TYPE )
00275 {
00276 MB_SET_ERR( MB_FAILURE, "Element type in matset " << id << " didn't get set correctly" );
00277 }
00278
00279 matset_data.number_nodes_per_element = ExoIIUtil::VerticesPerElement[matset_data.element_type];
00280
00281 // Number of nodes for this matset
00282 matset_data.number_elements = matset_data.elements->size();
00283
00284 // Total number of elements
00285 mesh_info.num_elements += matset_data.number_elements;
00286
00287 // Get the nodes for the elements
00288 mWriteIface->gather_nodes_from_elements( *matset_data.elements, mEntityMark, mesh_info.nodes );
00289
00290 if( !neusets.empty() )
00291 {
00292 // If there are neusets, keep track of which elements are being written out
00293 for( Range::iterator iter = matset_data.elements->begin(); iter != matset_data.elements->end(); ++iter )
00294 {
00295 unsigned char bit = 0x1;
00296 mbImpl->tag_set_data( mEntityMark, &( *iter ), 1, &bit );
00297 }
00298 }
00299
00300 matset_info.push_back( matset_data );
00301 }
00302
00303 // If user hasn't entered dimension, we figure it out
00304 if( mesh_info.num_dim == 0 )
00305 {
00306 // Never want 1 or zero dimensions
00307 if( highest_dimension_of_element_matsets < 2 )
00308 mesh_info.num_dim = 3;
00309 else
00310 mesh_info.num_dim = highest_dimension_of_element_matsets;
00311 }
00312
00313 Range::iterator range_iter, end_range_iter;
00314 range_iter = mesh_info.nodes.begin();
00315 end_range_iter = mesh_info.nodes.end();
00316
00317 mesh_info.num_nodes = mesh_info.nodes.size();
00318
00319 //------dirsets--------
00320
00321 vector_iter = dirsets.begin();
00322 end_vector_iter = dirsets.end();
00323
00324 for( ; vector_iter != end_vector_iter; ++vector_iter )
00325 {
00326 WriteTemplate::DirichletSetData dirset_data;
00327 dirset_data.id = 0;
00328 dirset_data.number_nodes = 0;
00329
00330 // Get the dirset's id
00331 if( mbImpl->tag_get_data( mDirichletSetTag, &( *vector_iter ), 1, &id ) != MB_SUCCESS )
00332 {
00333 MB_SET_ERR( MB_FAILURE, "Couldn't get id tag for dirset " << id );
00334 }
00335
00336 dirset_data.id = id;
00337
00338 std::vector< EntityHandle > node_vector;
00339 // Get the nodes of the dirset that are in mesh_info.nodes
00340 if( mbImpl->get_entities_by_handle( *vector_iter, node_vector, true ) != MB_SUCCESS )
00341 {
00342 MB_SET_ERR( MB_FAILURE, "Couldn't get nodes in dirset " << id );
00343 }
00344
00345 std::vector< EntityHandle >::iterator iter, end_iter;
00346 iter = node_vector.begin();
00347 end_iter = node_vector.end();
00348
00349 int j = 0;
00350 unsigned char node_marked = 0;
00351 ErrorCode result;
00352 for( ; iter != end_iter; ++iter )
00353 {
00354 if( TYPE_FROM_HANDLE( *iter ) != MBVERTEX ) continue;
00355 result = mbImpl->tag_get_data( mEntityMark, &( *iter ), 1, &node_marked );MB_CHK_SET_ERR( result, "Couldn't get mark data" );
00356
00357 if( 0x1 == node_marked ) dirset_data.nodes.push_back( *iter );
00358 j++;
00359 }
00360
00361 dirset_data.number_nodes = dirset_data.nodes.size();
00362 dirset_info.push_back( dirset_data );
00363 }
00364
00365 //------neusets--------
00366 vector_iter = neusets.begin();
00367 end_vector_iter = neusets.end();
00368
00369 for( ; vector_iter != end_vector_iter; ++vector_iter )
00370 {
00371 WriteTemplate::NeumannSetData neuset_data;
00372
00373 // Get the neuset's id
00374 if( mbImpl->tag_get_data( mNeumannSetTag, &( *vector_iter ), 1, &id ) != MB_SUCCESS ) return MB_FAILURE;
00375
00376 neuset_data.id = id;
00377 neuset_data.mesh_set_handle = *vector_iter;
00378
00379 // Get the sides in two lists, one forward the other reverse; starts with forward sense
00380 // by convention
00381 Range forward_elems, reverse_elems;
00382 if( get_neuset_elems( *vector_iter, 0, forward_elems, reverse_elems ) == MB_FAILURE ) return MB_FAILURE;
00383
00384 ErrorCode result = get_valid_sides( forward_elems, 1, neuset_data );MB_CHK_SET_ERR( result, "Couldn't get valid sides data" );
00385 result = get_valid_sides( reverse_elems, -1, neuset_data );MB_CHK_SET_ERR( result, "Couldn't get valid sides data" );
00386
00387 neuset_data.number_elements = neuset_data.elements.size();
00388 neuset_info.push_back( neuset_data );
00389 }
00390
00391 return MB_SUCCESS;
00392 }
00393
00394 ErrorCode WriteTemplate::get_valid_sides( Range& elems, const int sense, WriteTemplate::NeumannSetData& neuset_data )
00395 {
00396 // This is where we see if underlying element of side set element is included in output
00397
00398 unsigned char element_marked = 0;
00399 ErrorCode result;
00400 for( Range::iterator iter = elems.begin(); iter != elems.end(); ++iter )
00401 {
00402 // Should insert here if "side" is a quad/tri on a quad/tri mesh
00403 result = mbImpl->tag_get_data( mEntityMark, &( *iter ), 1, &element_marked );MB_CHK_SET_ERR( result, "Couldn't get mark data" );
00404
00405 if( 0x1 == element_marked )
00406 {
00407 neuset_data.elements.push_back( *iter );
00408
00409 // TJT TODO: the sense should really be # edges + 1or2
00410 neuset_data.side_numbers.push_back( ( sense == 1 ? 1 : 2 ) );
00411 }
00412 else
00413 { // Then "side" is probably a quad/tri on a hex/tet mesh
00414 std::vector< EntityHandle > parents;
00415 int dimension = CN::Dimension( TYPE_FROM_HANDLE( *iter ) );
00416
00417 // Get the adjacent parent element of "side"
00418 if( mbImpl->get_adjacencies( &( *iter ), 1, dimension + 1, false, parents ) != MB_SUCCESS )
00419 {
00420 MB_SET_ERR( MB_FAILURE, "Couldn't get adjacencies for neuset" );
00421 }
00422
00423 if( !parents.empty() )
00424 {
00425 // Make sure the adjacent parent element will be output
00426 for( unsigned int k = 0; k < parents.size(); k++ )
00427 {
00428 result = mbImpl->tag_get_data( mEntityMark, &( parents[k] ), 1, &element_marked );MB_CHK_SET_ERR( result, "Couldn't get mark data" );
00429
00430 int side_no, this_sense, this_offset;
00431 if( 0x1 == element_marked &&
00432 mbImpl->side_number( parents[k], *iter, side_no, this_sense, this_offset ) == MB_SUCCESS &&
00433 this_sense == sense )
00434 {
00435 neuset_data.elements.push_back( parents[k] );
00436 neuset_data.side_numbers.push_back( side_no + 1 );
00437 break;
00438 }
00439 }
00440 }
00441 else
00442 {
00443 MB_SET_ERR( MB_FAILURE, "No parent element exists for element in neuset " << neuset_data.id );
00444 }
00445 }
00446 }
00447
00448 return MB_SUCCESS;
00449 }
00450
00451 ErrorCode WriteTemplate::write_nodes( const int num_nodes, const Range& nodes, const int dimension )
00452 {
00453 // See if should transform coordinates
00454 ErrorCode result;
00455 Tag trans_tag;
00456 result = mbImpl->tag_get_handle( MESH_TRANSFORM_TAG_NAME, 16, MB_TYPE_DOUBLE, trans_tag );
00457 bool transform_needed = true;
00458 if( result == MB_TAG_NOT_FOUND ) transform_needed = false;
00459
00460 int num_coords_to_fill = transform_needed ? 3 : dimension;
00461
00462 std::vector< double* > coord_arrays( 3 );
00463 coord_arrays[0] = new double[num_nodes];
00464 coord_arrays[1] = new double[num_nodes];
00465 coord_arrays[2] = NULL;
00466
00467 if( num_coords_to_fill == 3 ) coord_arrays[2] = new double[num_nodes];
00468
00469 result = mWriteIface->get_node_coords( dimension, num_nodes, nodes, mGlobalIdTag, 0, coord_arrays );
00470 if( result != MB_SUCCESS )
00471 {
00472 delete[] coord_arrays[0];
00473 delete[] coord_arrays[1];
00474 if( coord_arrays[2] ) delete[] coord_arrays[2];
00475 return result;
00476 }
00477
00478 if( transform_needed )
00479 {
00480 double trans_matrix[16];
00481 const EntityHandle mesh = 0;
00482 result = mbImpl->tag_get_data( trans_tag, &mesh, 1, trans_matrix );MB_CHK_SET_ERR( result, "Couldn't get transform data" );
00483
00484 for( int i = 0; i < num_nodes; i++ )
00485 {
00486 double vec1[3];
00487 double vec2[3];
00488
00489 vec2[0] = coord_arrays[0][i];
00490 vec2[1] = coord_arrays[1][i];
00491 vec2[2] = coord_arrays[2][i];
00492
00493 for( int row = 0; row < 3; row++ )
00494 {
00495 vec1[row] = 0.0;
00496 for( int col = 0; col < 3; col++ )
00497 vec1[row] += ( trans_matrix[( row * 4 ) + col] * vec2[col] );
00498 }
00499
00500 coord_arrays[0][i] = vec1[0];
00501 coord_arrays[1][i] = vec1[1];
00502 coord_arrays[2][i] = vec1[2];
00503 }
00504 }
00505
00506 // Write the nodes
00507
00508 /* Template - write nodes to file here in some way */
00509
00510 // Clean up
00511 delete[] coord_arrays[0];
00512 delete[] coord_arrays[1];
00513 if( coord_arrays[2] ) delete[] coord_arrays[2];
00514
00515 return MB_SUCCESS;
00516 }
00517
00518 ErrorCode WriteTemplate::write_matsets(
00519 MeshInfo& /* mesh_info (commented out to remove warning) */,
00520 std::vector< WriteTemplate::MaterialSetData >& matset_data,
00521 std::vector< WriteTemplate::NeumannSetData >& /* neuset_data (commented out to remove warning) */ )
00522 {
00523 unsigned int i;
00524 std::vector< int > connect;
00525 const EntityHandle* connecth;
00526 int num_connecth;
00527 ErrorCode result;
00528
00529 // Don't usually have anywhere near 31 nodes per element
00530 connect.reserve( 31 );
00531 Range::iterator rit;
00532
00533 WriteTemplate::MaterialSetData matset;
00534 for( i = 0; i < matset_data.size(); i++ )
00535 {
00536 matset = matset_data[i];
00537
00538 for( rit = matset.elements->begin(); rit != matset.elements->end(); ++rit )
00539 {
00540 // Get the connectivity of this element
00541 result = mbImpl->get_connectivity( *rit, connecth, num_connecth );
00542 if( MB_SUCCESS != result ) return result;
00543
00544 // Get the vertex ids
00545 result = mbImpl->tag_get_data( mGlobalIdTag, connecth, num_connecth, &connect[0] );
00546 if( MB_SUCCESS != result ) return result;
00547
00548 // Write the data
00549 /* Template - write element connectivity here */
00550
00551 if( /* Template - check for error condition! */ false ) return MB_FAILURE;
00552 }
00553 }
00554
00555 return MB_SUCCESS;
00556 }
00557
00558 ErrorCode WriteTemplate::initialize_file( MeshInfo& mesh_info )
00559 {
00560 // Perform the initializations
00561
00562 int coord_size, ncoords;
00563
00564 coord_size = mesh_info.num_dim;
00565 std::cout << "Coord_size = " << coord_size << std::endl;
00566 /* Template - write coord size */
00567
00568 ncoords = mesh_info.num_nodes;
00569 std::cout << "ncoords = " << ncoords << std::endl;
00570 /* Template - write num nodes*/
00571
00572 /* Template - write information on the element types & numbers (depends
00573 on material and other sets) */
00574
00575 /* Node coordinate arrays: */
00576 /* Template - initialize variable to hold coordinate arrays */
00577
00578 return MB_SUCCESS;
00579 }
00580
00581 ErrorCode WriteTemplate::open_file( const char* filename )
00582 {
00583 // Not a valid filename
00584 if( strlen( (const char*)filename ) == 0 )
00585 {
00586 MB_SET_ERR( MB_FAILURE, "Output filename not specified" );
00587 }
00588
00589 /* Template - open file & store somewhere */
00590
00591 // File couldn't be opened
00592 if( /* Template - check for file open error here! */ false )
00593 {
00594 MB_SET_ERR( MB_FAILURE, "Cannot open " << filename );
00595 }
00596
00597 return MB_SUCCESS;
00598 }
00599
00600 ErrorCode WriteTemplate::get_neuset_elems( EntityHandle neuset,
00601 int current_sense,
00602 Range& forward_elems,
00603 Range& reverse_elems )
00604 {
00605 Range neuset_elems, neuset_meshsets;
00606
00607 // Get the sense tag; don't need to check return, might be an error if the tag
00608 // hasn't been created yet
00609 Tag sense_tag = 0;
00610 mbImpl->tag_get_handle( "SENSE", 1, MB_TYPE_INTEGER, sense_tag );
00611
00612 // Get the entities in this set
00613 ErrorCode result = mbImpl->get_entities_by_handle( neuset, neuset_elems, true );
00614 if( MB_FAILURE == result ) return result;
00615
00616 // Now remove the meshsets into the neuset_meshsets; first find the first meshset,
00617 Range::iterator range_iter = neuset_elems.begin();
00618 while( TYPE_FROM_HANDLE( *range_iter ) != MBENTITYSET && range_iter != neuset_elems.end() )
00619 ++range_iter;
00620
00621 // Then, if there are some, copy them into neuset_meshsets and erase from neuset_elems
00622 if( range_iter != neuset_elems.end() )
00623 {
00624 std::copy( range_iter, neuset_elems.end(), range_inserter( neuset_meshsets ) );
00625 neuset_elems.erase( range_iter, neuset_elems.end() );
00626 }
00627
00628 // OK, for the elements, check the sense of this set and copy into the right range
00629 // (if the sense is 0, copy into both ranges)
00630
00631 // Need to step forward on list until we reach the right dimension
00632 Range::iterator dum_it = neuset_elems.end();
00633 --dum_it;
00634 int target_dim = CN::Dimension( TYPE_FROM_HANDLE( *dum_it ) );
00635 dum_it = neuset_elems.begin();
00636 while( target_dim != CN::Dimension( TYPE_FROM_HANDLE( *dum_it ) ) && dum_it != neuset_elems.end() )
00637 ++dum_it;
00638
00639 if( current_sense == 1 || current_sense == 0 )
00640 std::copy( dum_it, neuset_elems.end(), range_inserter( forward_elems ) );
00641 if( current_sense == -1 || current_sense == 0 )
00642 std::copy( dum_it, neuset_elems.end(), range_inserter( reverse_elems ) );
00643
00644 // Now loop over the contained meshsets, getting the sense of those and calling this
00645 // function recursively
00646 for( range_iter = neuset_meshsets.begin(); range_iter != neuset_meshsets.end(); ++range_iter )
00647 {
00648 // First get the sense; if it's not there, by convention it's forward
00649 int this_sense;
00650 if( 0 == sense_tag || MB_FAILURE == mbImpl->tag_get_data( sense_tag, &( *range_iter ), 1, &this_sense ) )
00651 this_sense = 1;
00652
00653 // Now get all the entities on this meshset, with the proper (possibly reversed) sense
00654 get_neuset_elems( *range_iter, this_sense * current_sense, forward_elems, reverse_elems );
00655 }
00656
00657 return result;
00658 }
00659
00660 } // namespace moab