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 "WriteGMV.hpp" 00025 00026 #include "moab/Interface.hpp" 00027 #include "Internals.hpp" 00028 #include "moab/Range.hpp" 00029 #include "moab/CN.hpp" 00030 #include "MBTagConventions.hpp" 00031 #include "moab/WriteUtilIface.hpp" 00032 #include <fstream> 00033 #include <cassert> 00034 00035 namespace moab 00036 { 00037 00038 const char* WriteGMV::gmvTypeNames[] = { "", "line", "tri", "quad", "", "tet", "pyramid", "prism", "", "hex", "", "" }; 00039 00040 WriterIface* WriteGMV::factory( Interface* iface ) 00041 { 00042 return new WriteGMV( iface ); 00043 } 00044 00045 WriteGMV::WriteGMV( Interface* impl ) : mbImpl( impl ) 00046 { 00047 assert( impl != NULL ); 00048 00049 impl->query_interface( mWriteIface ); 00050 00051 // initialize in case tag_get_handle fails below 00052 mMaterialSetTag = 0; 00053 mDirichletSetTag = 0; 00054 mNeumannSetTag = 0; 00055 mHasMidNodesTag = 0; 00056 mGeomDimensionTag = 0; 00057 mGlobalIdTag = 0; 00058 00059 //! get and cache predefined tag handles 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 int dum_val_array[] = { -1, -1, -1, -1 }; 00075 impl->tag_get_handle( HAS_MID_NODES_TAG_NAME, 4, MB_TYPE_INTEGER, mHasMidNodesTag, MB_TAG_SPARSE | MB_TAG_CREAT, 00076 dum_val_array ); 00077 } 00078 00079 WriteGMV::~WriteGMV() 00080 { 00081 mbImpl->release_interface( mWriteIface ); 00082 } 00083 00084 ErrorCode WriteGMV::write_file( const char* file_name, 00085 const EntityHandle output_set, 00086 const int user_dimension, 00087 const bool mesh, 00088 const bool poly_mesh ) 00089 { 00090 // general function for writing a mesh 00091 00092 ErrorCode result = MB_SUCCESS; 00093 00094 // initialize file 00095 00096 if( mesh ) 00097 { 00098 result = local_write_mesh( file_name, output_set, user_dimension, true, false ); 00099 if( MB_SUCCESS != result ) return result; 00100 } 00101 00102 if( poly_mesh ) 00103 { 00104 result = local_write_mesh( file_name, output_set, user_dimension, false, true ); 00105 if( MB_SUCCESS != result ) return result; 00106 } 00107 00108 return result; 00109 } 00110 00111 ErrorCode WriteGMV::write_file( const char* filename, 00112 const bool, 00113 const FileOptions& /*opts*/, 00114 const EntityHandle* output_sets, 00115 const int num_output_sets, 00116 const std::vector< std::string >&, 00117 const Tag*, 00118 int, 00119 int dimension ) 00120 { 00121 EntityHandle output_set = 0; 00122 if( output_sets && num_output_sets > 0 ) 00123 { 00124 if( num_output_sets > 1 ) return MB_FAILURE; 00125 output_set = output_sets[0]; 00126 } 00127 00128 if( dimension == 0 ) 00129 { 00130 mbImpl->get_dimension( dimension ); 00131 } 00132 00133 return write_file( filename, output_set, dimension, true, true ); 00134 } 00135 00136 ErrorCode WriteGMV::local_write_mesh( const char* file_name, 00137 const EntityHandle output_set, 00138 const int user_dimension, 00139 const bool mesh, 00140 const bool poly_mesh ) 00141 { 00142 std::ofstream ofile; 00143 ErrorCode result; 00144 00145 if( mesh ) 00146 { 00147 // need to insert ".gmv" 00148 std::string tmp_name( file_name ); 00149 tmp_name += ".gmv"; 00150 ofile.open( tmp_name.c_str() ); 00151 } 00152 else if( poly_mesh ) 00153 { 00154 // need to insert ".poly.gmv" 00155 std::string tmp_name( file_name ); 00156 tmp_name += ".poly.gmv"; 00157 ofile.open( tmp_name.c_str() ); 00158 } 00159 00160 ofile << "gmvinput ascii" << std::endl; 00161 00162 // get elements to be output 00163 Range dum_range, elements, all_verts; 00164 EntityType otype; 00165 if( poly_mesh ) 00166 { 00167 result = mbImpl->get_entities_by_type( output_set, MBPOLYGON, elements, true ); 00168 if( MB_SUCCESS != result ) return result; 00169 } 00170 else 00171 { 00172 for( otype = CN::TypeDimensionMap[user_dimension].first; otype <= CN::TypeDimensionMap[user_dimension].second; 00173 otype++ ) 00174 { 00175 if( otype == MBPOLYGON || otype == MBPOLYHEDRON ) continue; 00176 dum_range.clear(); 00177 result = mbImpl->get_entities_by_type( output_set, otype, dum_range, true ); 00178 if( MB_SUCCESS != result ) return result; 00179 00180 std::copy( dum_range.begin(), dum_range.end(), range_inserter( elements ) ); 00181 } 00182 } 00183 00184 // gather the vertices in these elements 00185 result = mbImpl->get_adjacencies( elements, 0, false, all_verts, Interface::UNION ); 00186 if( MB_SUCCESS != result ) return result; 00187 00188 int num_verts = all_verts.size(); 00189 00190 // allocate coordinate arrays and put pointers to them in a list 00191 double* xcoord = new double[num_verts]; 00192 double* ycoord = new double[num_verts]; 00193 double* zcoord = new double[num_verts]; 00194 std::vector< double* > coord_arrays; 00195 coord_arrays.push_back( xcoord ); 00196 coord_arrays.push_back( ycoord ); 00197 coord_arrays.push_back( zcoord ); 00198 00199 // fill them in, writing id tags at the same time 00200 result = mWriteIface->get_node_coords( 3, num_verts, all_verts, mGlobalIdTag, 1, coord_arrays ); 00201 if( MB_SUCCESS != result ) return result; 00202 00203 int i, j; 00204 00205 //======================================== 00206 // WRITE COORDINATE DATA TO FILE HERE 00207 00208 ofile << "nodev " << num_verts << std::endl; 00209 for( i = 0; i < num_verts; i++ ) 00210 ofile << xcoord[i] << " " << ycoord[i] << " " << zcoord[i] << std::endl; 00211 00212 //======================================== 00213 00214 delete[] xcoord; 00215 delete[] ycoord; 00216 delete[] zcoord; 00217 00218 // iterate over types in selected dimension 00219 00220 std::vector< int > connect; 00221 std::vector< EntityHandle > connecth; 00222 00223 if( mesh ) 00224 { 00225 Range sub_range; 00226 00227 ofile << "cells " << elements.size() << std::endl; 00228 00229 for( otype = CN::TypeDimensionMap[user_dimension].first; otype <= CN::TypeDimensionMap[user_dimension].second; 00230 otype++ ) 00231 { 00232 00233 if( otype == MBPOLYGON || otype == MBPOLYHEDRON ) continue; 00234 00235 // get the first element of this type in the range, and one past the last 00236 Range::iterator lower = 00237 Range::lower_bound( elements.begin(), elements.end(), CREATE_HANDLE( otype, MB_START_ID, i ) ); 00238 Range::iterator upper = 00239 Range::lower_bound( elements.begin(), elements.end(), CREATE_HANDLE( otype + 1, MB_START_ID, i ) ); 00240 00241 if( lower == upper ) continue; 00242 00243 // copy these elements into a subrange 00244 sub_range.clear(); 00245 std::copy( lower, upper, range_inserter( sub_range ) ); 00246 00247 // make sure the connectivity array is big enough 00248 int verts_per = CN::VerticesPerEntity( otype ); 00249 if( connect.size() < verts_per * sub_range.size() ) connect.resize( verts_per * sub_range.size() ); 00250 00251 // get the connectivity 00252 result = mWriteIface->get_element_connect( sub_range.size(), verts_per, mGlobalIdTag, sub_range, 00253 mGlobalIdTag, 1, &connect[0] ); 00254 if( MB_SUCCESS != result ) return result; 00255 00256 //======================================== 00257 // WRITE CONNECTIVITY DATA TO FILE HERE 00258 00259 for( i = 0; i < (int)sub_range.size(); i++ ) 00260 { 00261 ofile << gmvTypeNames[otype] << " " << verts_per << std::endl; 00262 for( j = i * verts_per; j < (int)( i + 1 ) * verts_per; j++ ) 00263 ofile << connect[j] << " "; 00264 ofile << std::endl; 00265 } 00266 00267 //======================================== 00268 } 00269 } 00270 00271 else if( poly_mesh ) 00272 { 00273 00274 // write polygons/hedra, if any 00275 Range polygons, polyhedra; 00276 result = mbImpl->get_entities_by_type( output_set, MBPOLYGON, polygons, true ); 00277 if( MB_SUCCESS != result ) return result; 00278 00279 result = mbImpl->get_entities_by_type( output_set, MBPOLYHEDRON, polyhedra, true ); 00280 if( MB_SUCCESS != result ) return result; 00281 00282 if( polygons.size() == 0 ) return result; 00283 00284 // mark polyhedra with global ids 00285 result = mWriteIface->assign_ids( polyhedra, mGlobalIdTag, 1 ); 00286 if( MB_SUCCESS != result ) return result; 00287 00288 ofile << "faces " << polygons.size() << " " << polyhedra.size() << std::endl; 00289 00290 for( Range::iterator rit = polygons.begin(); rit != polygons.end(); ++rit ) 00291 { 00292 // get the vertices 00293 connecth.clear(); 00294 result = mbImpl->get_connectivity( &( *rit ), 1, connecth, true ); 00295 if( MB_SUCCESS != result ) return result; 00296 00297 if( 0 == connecth.size() ) continue; 00298 00299 // get the polyhedra, if any 00300 if( user_dimension == 3 ) 00301 { 00302 polyhedra.clear(); 00303 result = mbImpl->get_adjacencies( Range( *rit, *rit ), 3, false, polyhedra ); 00304 if( MB_SUCCESS != result ) return result; 00305 00306 // put them in the connect array 00307 connecth.push_back( ( polyhedra.size() > 0 ? *polyhedra.begin() : 0 ) ); 00308 connecth.push_back( ( polyhedra.size() > 1 ? *polyhedra.rbegin() : 0 ) ); 00309 } 00310 00311 // replace handles with ids 00312 connect.resize( connecth.size() + 2 ); 00313 00314 // pre-set polyhedra ids in case there aren't any 00315 connect[connecth.size()] = 0; 00316 connect[connecth.size() + 1] = 0; 00317 result = 00318 mbImpl->tag_get_data( mGlobalIdTag, &connecth[0], connecth.size() - 2 + polyhedra.size(), &connect[0] ); 00319 if( MB_SUCCESS != result ) return result; 00320 00321 // write the data 00322 ofile << connecth.size() - 2; 00323 00324 for( i = 0; i < (int)connecth.size(); i++ ) 00325 ofile << " " << connect[i]; 00326 00327 ofile << std::endl; 00328 } 00329 } 00330 00331 ofile << std::endl << "endgmv" << std::endl; 00332 00333 ofile.close(); 00334 00335 return MB_SUCCESS; 00336 } 00337 00338 } // namespace moab