MOAB: Mesh Oriented datABase  (version 5.2.1)
WriteGMV.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines