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 <utility> 00027 #include <algorithm> 00028 #include <ctime> 00029 #include <string> 00030 #include <vector> 00031 #include <cstdio> 00032 #include <cstring> 00033 #include <iostream> 00034 00035 #include "moab/Interface.hpp" 00036 #include "moab/Range.hpp" 00037 #include "moab/CN.hpp" 00038 #include <cassert> 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