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