LCOV - code coverage report
Current view: top level - src/io - WriteGmsh.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 1 144 0.7 %
Date: 2020-12-16 07:07:30 Functions: 2 7 28.6 %
Branches: 2 458 0.4 %

           Branch data     Line data    Source code
       1                 :            : #include "WriteGmsh.hpp"
       2                 :            : #include "moab/CN.hpp"
       3                 :            : #include "MBTagConventions.hpp"
       4                 :            : #include "MBParallelConventions.h"
       5                 :            : #include "moab/Interface.hpp"
       6                 :            : #include "moab/Range.hpp"
       7                 :            : #include "moab/WriteUtilIface.hpp"
       8                 :            : #include "moab/FileOptions.hpp"
       9                 :            : #include "GmshUtil.hpp"
      10                 :            : 
      11                 :            : #include <fstream>
      12                 :            : #include <map>
      13                 :            : #include <set>
      14                 :            : 
      15                 :            : namespace moab
      16                 :            : {
      17                 :            : 
      18                 :            : const int DEFAULT_PRECISION = 10;
      19                 :            : 
      20                 :          0 : WriterIface* WriteGmsh::factory( Interface* iface )
      21                 :            : {
      22         [ #  # ]:          0 :     return new WriteGmsh( iface );
      23                 :            : }
      24                 :            : 
      25                 :          0 : WriteGmsh::WriteGmsh( Interface* impl ) : mbImpl( impl )
      26                 :            : {
      27         [ #  # ]:          0 :     impl->query_interface( mWriteIface );
      28                 :          0 : }
      29                 :            : 
      30                 :          0 : WriteGmsh::~WriteGmsh()
      31                 :            : {
      32                 :          0 :     mbImpl->release_interface( mWriteIface );
      33         [ #  # ]:          0 : }
      34                 :            : 
      35                 :            : // A structure to store per-element information.
      36                 :            : struct ElemInfo
      37                 :            : {
      38                 :          0 :     void set( int st, int idt )
      39                 :            :     {
      40         [ #  # ]:          0 :         while( count < st )
      41                 :          0 :             sets[count++] = 0;
      42                 :          0 :         sets[count++] = idt;
      43                 :          0 :     }
      44                 :            :     int count;    // Number of valid entries in sets[]
      45                 :            :     int sets[3];  // IDs of owning block, geom, and partition; respectively
      46                 :            :     int id;       // Global ID of element
      47                 :            :     int type;     // Gmsh element type
      48                 :            : };
      49                 :            : 
      50                 :            : //! Writes out a file
      51                 :          0 : ErrorCode WriteGmsh::write_file( const char* file_name, const bool overwrite, const FileOptions& options,
      52                 :            :                                  const EntityHandle* output_list, const int num_sets,
      53                 :            :                                  const std::vector< std::string >& /* qa_list */, const Tag* /* tag_list */,
      54                 :            :                                  int /* num_tags */, int /* export_dimension */ )
      55                 :            : {
      56                 :            :     ErrorCode rval;
      57                 :          0 :     Tag global_id = 0, block_tag = 0, geom_tag = 0, prtn_tag = 0;
      58                 :            : 
      59         [ #  # ]:          0 :     if( !overwrite )
      60                 :            :     {
      61         [ #  # ]:          0 :         rval = mWriteIface->check_doesnt_exist( file_name );
      62         [ #  # ]:          0 :         if( MB_SUCCESS != rval ) return rval;
      63                 :            :     }
      64                 :            : 
      65                 :            :     // Get tags
      66         [ #  # ]:          0 :     global_id = mbImpl->globalId_tag();
      67         [ #  # ]:          0 :     mbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, block_tag );
      68 [ #  # ][ #  # ]:          0 :     if( global_id ) mbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag );
      69         [ #  # ]:          0 :     mbImpl->tag_get_handle( PARALLEL_PARTITION_TAG_NAME, 1, MB_TYPE_INTEGER, prtn_tag );
      70                 :            : 
      71                 :            :     // Define arrays to hold entity sets of interest
      72 [ #  # ][ #  # ]:          0 :     Range sets[3];
                 [ #  # ]
      73                 :          0 :     Tag set_tags[] = { block_tag, geom_tag, prtn_tag };
      74                 :          0 :     Tag set_ids[]  = { block_tag, 0 /*global_id*/, prtn_tag };
      75                 :            : 
      76                 :            :     // Get entities to write
      77 [ #  # ][ #  # ]:          0 :     Range elements, nodes;
      78         [ #  # ]:          0 :     if( !output_list )
      79                 :            :     {
      80         [ #  # ]:          0 :         rval = mbImpl->get_entities_by_dimension( 0, 0, nodes, false );
      81         [ #  # ]:          0 :         if( MB_SUCCESS != rval ) return rval;
      82         [ #  # ]:          0 :         for( int d = 1; d <= 3; ++d )
      83                 :            :         {
      84         [ #  # ]:          0 :             Range tmp_range;
      85         [ #  # ]:          0 :             rval = mbImpl->get_entities_by_dimension( 0, d, tmp_range, false );
      86         [ #  # ]:          0 :             if( MB_SUCCESS != rval ) return rval;
      87 [ #  # ][ #  # ]:          0 :             elements.merge( tmp_range );
      88                 :          0 :         }
      89                 :            : 
      90         [ #  # ]:          0 :         for( int s = 0; s < 3; ++s )
      91                 :            :         {
      92         [ #  # ]:          0 :             if( set_tags[s] )
      93                 :            :             {
      94         [ #  # ]:          0 :                 rval = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, set_tags + s, 0, 1, sets[s] );
      95         [ #  # ]:          0 :                 if( MB_SUCCESS != rval ) return rval;
      96                 :            :             }
      97                 :            :         }
      98                 :            :     }
      99                 :            :     else
     100                 :            :     {
     101         [ #  # ]:          0 :         for( int i = 0; i < num_sets; ++i )
     102                 :            :         {
     103                 :          0 :             EntityHandle set = output_list[i];
     104         [ #  # ]:          0 :             for( int d = 1; d < 3; ++d )
     105                 :            :             {
     106 [ #  # ][ #  # ]:          0 :                 Range tmp_range, tmp_nodes;
                 [ #  # ]
     107         [ #  # ]:          0 :                 rval = mbImpl->get_entities_by_dimension( set, d, tmp_range, true );
     108         [ #  # ]:          0 :                 if( rval != MB_SUCCESS ) return rval;
     109         [ #  # ]:          0 :                 elements.merge( tmp_range );
     110         [ #  # ]:          0 :                 rval = mbImpl->get_adjacencies( tmp_range, set, false, tmp_nodes );
     111         [ #  # ]:          0 :                 if( rval != MB_SUCCESS ) return rval;
     112 [ #  # ][ #  # ]:          0 :                 nodes.merge( tmp_nodes );
     113                 :          0 :             }
     114                 :            : 
     115         [ #  # ]:          0 :             for( int s = 0; s < 3; ++s )
     116                 :            :             {
     117         [ #  # ]:          0 :                 if( set_tags[s] )
     118                 :            :                 {
     119         [ #  # ]:          0 :                     Range tmp_range;
     120         [ #  # ]:          0 :                     rval = mbImpl->get_entities_by_type_and_tag( set, MBENTITYSET, set_tags + s, 0, 1, tmp_range );
     121         [ #  # ]:          0 :                     if( MB_SUCCESS != rval ) return rval;
     122         [ #  # ]:          0 :                     sets[s].merge( tmp_range );
     123                 :            :                     int junk;
     124         [ #  # ]:          0 :                     rval = mbImpl->tag_get_data( set_tags[s], &set, 1, &junk );
     125 [ #  # ][ #  # ]:          0 :                     if( MB_SUCCESS == rval ) sets[s].insert( set );
                 [ #  # ]
     126                 :            :                 }
     127                 :            :             }
     128                 :            :         }
     129                 :            :     }
     130                 :            : 
     131 [ #  # ][ #  # ]:          0 :     if( elements.empty() ) { MB_SET_ERR( MB_ENTITY_NOT_FOUND, "Nothing to write" ); }
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     132                 :            : 
     133                 :            :     // Get global IDs for all elements.
     134                 :            :     // First try to get from tag.  If tag is not defined or not set
     135                 :            :     // for all elements, use handle value instead.
     136 [ #  # ][ #  # ]:          0 :     std::vector< int > global_id_array( elements.size() );
     137                 :          0 :     std::vector< int >::iterator id_iter;
     138 [ #  # ][ #  # ]:          0 :     if( !global_id || MB_SUCCESS != mbImpl->tag_get_data( global_id, elements, &global_id_array[0] ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     139                 :            :     {
     140                 :          0 :         id_iter = global_id_array.begin();
     141 [ #  # ][ #  # ]:          0 :         for( Range::iterator i = elements.begin(); i != elements.end(); ++i, ++id_iter )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     142 [ #  # ][ #  # ]:          0 :             *id_iter = mbImpl->id_from_handle( *i );
                 [ #  # ]
     143                 :            :     }
     144                 :            : 
     145                 :            :     // Figure out the maximum ID value so we know where to start allocating
     146                 :            :     // new IDs when we encounter ID conflicts.
     147                 :          0 :     int max_id = 0;
     148 [ #  # ][ #  # ]:          0 :     for( id_iter = global_id_array.begin(); id_iter != global_id_array.end(); ++id_iter )
                 [ #  # ]
     149 [ #  # ][ #  # ]:          0 :         if( *id_iter > max_id ) max_id = *id_iter;
                 [ #  # ]
     150                 :            : 
     151                 :            :     // Initialize ElemInfo struct for each element
     152         [ #  # ]:          0 :     std::map< EntityHandle, ElemInfo > elem_sets;  // Per-element info
     153         [ #  # ]:          0 :     std::set< int > elem_global_ids;               // Temporary for finding duplicate IDs
     154                 :          0 :     id_iter = global_id_array.begin();
     155                 :            :     // Iterate backwards to give highest-dimension entities first dibs for
     156                 :            :     // a conflicting ID.
     157 [ #  # ][ #  # ]:          0 :     for( Range::reverse_iterator i = elements.rbegin(); i != elements.rend(); ++i )
         [ #  # ][ #  # ]
                 [ #  # ]
     158                 :            :     {
     159         [ #  # ]:          0 :         int id = *id_iter;
     160         [ #  # ]:          0 :         ++id_iter;
     161 [ #  # ][ #  # ]:          0 :         if( !elem_global_ids.insert( id ).second ) id = ++max_id;
     162                 :            : 
     163 [ #  # ][ #  # ]:          0 :         ElemInfo& ei = elem_sets[*i];
     164                 :          0 :         ei.count     = 0;
     165                 :          0 :         ei.id        = id;
     166                 :            : 
     167 [ #  # ][ #  # ]:          0 :         EntityType type = mbImpl->type_from_handle( *i );
     168                 :            :         int num_vtx;
     169                 :            :         const EntityHandle* conn;
     170 [ #  # ][ #  # ]:          0 :         rval = mbImpl->get_connectivity( *i, conn, num_vtx );
     171         [ #  # ]:          0 :         if( MB_SUCCESS != rval ) return rval;
     172                 :            : 
     173         [ #  # ]:          0 :         ei.type = GmshUtil::get_gmsh_type( type, num_vtx );
     174         [ #  # ]:          0 :         if( ei.type < 0 )
     175                 :            :         {
     176 [ #  # ][ #  # ]:          0 :             MB_SET_ERR( MB_FILE_WRITE_ERROR, "Gmem file format does not support element of type "
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     177                 :            :                                                  << CN::EntityTypeName( type ) << " with " << num_vtx << " vertices" );
     178                 :            :         }
     179                 :            :     }
     180                 :            :     // Don't need these any more, free memory.
     181                 :          0 :     elem_global_ids.clear();
     182                 :          0 :     global_id_array.clear();
     183                 :            : 
     184                 :            :     // For each material set, geometry set, or partition; store
     185                 :            :     // the ID of the set on each element.
     186         [ #  # ]:          0 :     for( int s = 0; s < 3; ++s )
     187                 :            :     {
     188         [ #  # ]:          0 :         if( !set_tags[s] ) continue;
     189                 :            : 
     190 [ #  # ][ #  # ]:          0 :         for( Range::iterator i = sets[s].begin(); i != sets[s].end(); ++i )
         [ #  # ][ #  # ]
                 [ #  # ]
     191                 :            :         {
     192                 :            :             int id;
     193         [ #  # ]:          0 :             if( set_ids[s] )
     194                 :            :             {
     195 [ #  # ][ #  # ]:          0 :                 rval = mbImpl->tag_get_data( set_ids[s], &*i, 1, &id );
     196         [ #  # ]:          0 :                 if( MB_SUCCESS != rval ) return rval;
     197                 :            :             }
     198                 :            :             else
     199 [ #  # ][ #  # ]:          0 :                 id = mbImpl->id_from_handle( *i );
     200                 :            : 
     201         [ #  # ]:          0 :             Range elems;
     202 [ #  # ][ #  # ]:          0 :             rval = mbImpl->get_entities_by_handle( *i, elems );
     203         [ #  # ]:          0 :             if( MB_SUCCESS != rval ) return rval;
     204                 :            : 
     205 [ #  # ][ #  # ]:          0 :             elems = intersect( elems, elements );
     206 [ #  # ][ #  # ]:          0 :             for( Range::iterator j = elems.begin(); j != elems.end(); ++j )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     207 [ #  # ][ #  # ]:          0 :                 elem_sets[*j].set( s, id );
                 [ #  # ]
     208                 :          0 :         }
     209                 :            :     }
     210                 :            : 
     211                 :            :     // Create file
     212 [ #  # ][ #  # ]:          0 :     std::ofstream out( file_name );
     213 [ #  # ][ #  # ]:          0 :     if( !out ) return MB_FILE_DOES_NOT_EXIST;
     214                 :            : 
     215                 :            :     // Write header
     216 [ #  # ][ #  # ]:          0 :     out << "$MeshFormat" << std::endl;
     217 [ #  # ][ #  # ]:          0 :     out << "2.0 0 " << sizeof( double ) << std::endl;
                 [ #  # ]
     218 [ #  # ][ #  # ]:          0 :     out << "$EndMeshFormat" << std::endl;
     219                 :            : 
     220                 :            :     // Set precision for node coordinates
     221                 :            :     int precision;
     222 [ #  # ][ #  # ]:          0 :     if( MB_SUCCESS != options.get_int_option( "PRECISION", precision ) ) precision = DEFAULT_PRECISION;
     223         [ #  # ]:          0 :     const int old_precision = out.precision();
     224         [ #  # ]:          0 :     out.precision( precision );
     225                 :            : 
     226                 :            :     // Write nodes
     227 [ #  # ][ #  # ]:          0 :     out << "$Nodes" << std::endl;
     228 [ #  # ][ #  # ]:          0 :     out << nodes.size() << std::endl;
                 [ #  # ]
     229 [ #  # ][ #  # ]:          0 :     std::vector< double > coords( 3 * nodes.size() );
     230 [ #  # ][ #  # ]:          0 :     rval = mbImpl->get_coords( nodes, &coords[0] );
     231         [ #  # ]:          0 :     if( MB_SUCCESS != rval ) return rval;
     232                 :          0 :     std::vector< double >::iterator c = coords.begin();
     233 [ #  # ][ #  # ]:          0 :     for( Range::iterator i = nodes.begin(); i != nodes.end(); ++i )
         [ #  # ][ #  # ]
                 [ #  # ]
     234                 :            :     {
     235 [ #  # ][ #  # ]:          0 :         out << mbImpl->id_from_handle( *i );
                 [ #  # ]
     236 [ #  # ][ #  # ]:          0 :         out << " " << *c;
                 [ #  # ]
     237         [ #  # ]:          0 :         ++c;
     238 [ #  # ][ #  # ]:          0 :         out << " " << *c;
                 [ #  # ]
     239         [ #  # ]:          0 :         ++c;
     240 [ #  # ][ #  # ]:          0 :         out << " " << *c;
                 [ #  # ]
     241         [ #  # ]:          0 :         ++c;
     242         [ #  # ]:          0 :         out << std::endl;
     243                 :            :     }
     244 [ #  # ][ #  # ]:          0 :     out << "$EndNodes" << std::endl;
     245                 :          0 :     coords.clear();
     246                 :            : 
     247                 :            :     // Restore stream state
     248         [ #  # ]:          0 :     out.precision( old_precision );
     249                 :            : 
     250                 :            :     // Write elements
     251 [ #  # ][ #  # ]:          0 :     out << "$Elements" << std::endl;
     252 [ #  # ][ #  # ]:          0 :     out << elem_sets.size() << std::endl;
     253 [ #  # ][ #  # ]:          0 :     for( std::map< EntityHandle, ElemInfo >::iterator i = elem_sets.begin(); i != elem_sets.end(); ++i )
                 [ #  # ]
     254                 :            :     {
     255                 :            :         int num_vtx;
     256                 :            :         const EntityHandle* conn;
     257 [ #  # ][ #  # ]:          0 :         rval = mbImpl->get_connectivity( i->first, conn, num_vtx );
     258         [ #  # ]:          0 :         if( MB_SUCCESS != rval ) return rval;
     259 [ #  # ][ #  # ]:          0 :         out << i->second.id << ' ' << i->second.type << ' ' << i->second.count;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     260 [ #  # ][ #  # ]:          0 :         for( int j = 0; j < i->second.count; ++j )
     261 [ #  # ][ #  # ]:          0 :             out << ' ' << i->second.sets[j];
                 [ #  # ]
     262                 :            : 
     263         [ #  # ]:          0 :         const int* order = GmshUtil::gmshElemTypes[i->second.type].node_order;
     264                 :            : 
     265                 :            :         // Need to re-order vertices
     266         [ #  # ]:          0 :         if( order )
     267                 :            :         {
     268         [ #  # ]:          0 :             for( int j = 0; j < num_vtx; ++j )
     269 [ #  # ][ #  # ]:          0 :                 out << ' ' << mbImpl->id_from_handle( conn[order[j]] );
                 [ #  # ]
     270                 :            :         }
     271                 :            :         else
     272                 :            :         {
     273         [ #  # ]:          0 :             for( int j = 0; j < num_vtx; ++j )
     274 [ #  # ][ #  # ]:          0 :                 out << ' ' << mbImpl->id_from_handle( conn[j] );
                 [ #  # ]
     275                 :            :         }
     276         [ #  # ]:          0 :         out << std::endl;
     277                 :            :     }
     278 [ #  # ][ #  # ]:          0 :     out << "$EndElements" << std::endl;
     279                 :            : 
     280                 :            :     // Done
     281         [ #  # ]:          0 :     return MB_SUCCESS;
           [ #  #  #  # ]
     282                 :            : }
     283                 :            : 
     284 [ +  - ][ +  - ]:        228 : }  // namespace moab

Generated by: LCOV version 1.11