Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
ReaderWriterSet.cpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 #include "moab/Core.hpp"
17 
18 #include "moab/ReaderWriterSet.hpp"
19 #include "moab/ReaderIface.hpp"
20 #include "moab/WriterIface.hpp"
21 
22 #include "ReadVtk.hpp"
23 #include "ReadSTL.hpp"
24 #include "ReadGmsh.hpp"
25 #include "ReadIDEAS.hpp"
26 #include "ReadMCNP5.hpp"
27 #include "ReadOBJ.hpp"
28 #include "ReadNASTRAN.hpp"
29 #include "ReadRTT.hpp"
30 #include "ReadABAQUS.hpp"
31 #include "ReadSms.hpp"
32 #include "Tqdcfr.hpp"
33 #include "ReadTetGen.hpp"
34 #include "ReadSmf.hpp"
35 #include "ReadTemplate.hpp"
36 
37 #include "WriteAns.hpp"
38 #include "WriteVtk.hpp"
39 #include "WriteGMV.hpp"
40 #include "WriteSTL.hpp"
41 #include "WriteGmsh.hpp"
42 #include "WriteSmf.hpp"
43 #include "WriteTemplate.hpp"
44 
45 #ifdef MOAB_HAVE_NETCDF
46 #include "ReadNCDF.hpp"
47 #include "WriteNCDF.hpp"
48 #include "WriteNC.hpp"
49 #include "WriteSLAC.hpp"
50 #include "ReadNC.hpp"
51 #endif
52 
53 // 2nd include of ReadNC/WriteNC in case we have pnetcdf and not netcdf
54 #if defined( MOAB_HAVE_PNETCDF ) && !defined( MOAB_HAVE_NETCDF )
55 #include "ReadNC.hpp"
56 #include "WriteNC.hpp"
57 #endif
58 
59 #ifdef MOAB_HAVE_CGNS
60 #include "ReadCGNS.hpp"
61 #include "WriteCGNS.hpp"
62 #endif
63 
64 #ifdef MOAB_HAVE_CCMIO
65 #include "ReadCCMIO.hpp"
66 #include "WriteCCMIO.hpp"
67 #endif
68 
69 #ifdef MOAB_HAVE_DAMSEL
70 #include "WriteDamsel.hpp"
71 #include "ReadDamsel.hpp"
72 #endif
73 
74 #ifdef MOAB_HAVE_HDF5
75 #include "ReadHDF5.hpp"
76 #ifdef MOAB_HAVE_HDF5_PARALLEL
77 #include "WriteHDF5Parallel.hpp"
78 #else
79 #include "WriteHDF5.hpp"
80 #endif
81 #endif
82 
83 #include <algorithm>
84 
85 namespace moab
86 {
87 
88 ReaderWriterSet::ReaderWriterSet( Core* mdb ) : mbCore( mdb )
89 {
90 #ifdef MOAB_HAVE_HDF5
91  const char* hdf5_sufxs[] = { "h5m", "mhdf", NULL };
92 #ifdef MOAB_HAVE_HDF5_PARALLEL
93  register_factory( ReadHDF5::factory, WriteHDF5Parallel::factory, "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
94 #else
95  register_factory( ReadHDF5::factory, WriteHDF5::factory, "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
96 #endif
97 #endif
98 
99 #ifdef MOAB_HAVE_NETCDF
100  const char* exo_sufxs[] = { "exo", "exoII", "exo2", "g", "gen", NULL };
101  register_factory( ReadNCDF::factory, WriteNCDF::factory, "Exodus II", exo_sufxs, "EXODUS" );
102  register_factory( ReadNC::factory, WriteNC::factory, "Climate NC", "nc", "NC" );
103 #elif defined( MOAB_HAVE_PNETCDF )
104  // PNetCDF-only build: no Exodus (ReadNCDF needs serial NetCDF), but the climate NC
105  // reader/writer works for classic CDF files through the PNetCDF dispatch layer.
106  register_factory( ReadNC::factory, WriteNC::factory, "Climate NC", "nc", "NC" );
107 #endif
108 
109 #ifdef MOAB_HAVE_CGNS
110  const char* cgns_sufxs[] = { "cgns", NULL };
111  register_factory( ReadCGNS::factory, WriteCGNS::factory, "CGNS", cgns_sufxs, "CGNS" );
112 #endif
113 
114  register_factory( ReadIDEAS::factory, NULL, "IDEAS format", "unv", "UNV" );
115 
116  register_factory( ReadMCNP5::factory, NULL, "MCNP5 format", "meshtal", "MESHTAL" );
117 
118  const char* nastran_sufxs[] = { "nas", "bdf", NULL };
119  register_factory( ReadNASTRAN::factory, NULL, "NASTRAN format", nastran_sufxs, "NAS" );
120 
121  register_factory( ReadABAQUS::factory, NULL, "ABAQUS INP mesh format", "abq", "Abaqus mesh" );
122 
123  register_factory( ReadRTT::factory, NULL, "RTT Mesh Format", "rtt", "Atilla RTT Mesh" );
124 
125  register_factory( ReadVtk::factory, WriteVtk::factory, "Kitware VTK", "vtk", "VTK" );
126 
127  register_factory( ReadOBJ::factory, NULL, "OBJ mesh format", "obj", "OBJ mesh" );
128 
129  register_factory( ReadSms::factory, NULL, "RPI SMS", "sms", "SMS" );
130 
131  register_factory( Tqdcfr::factory, NULL, "Cubit", "cub", "CUBIT" );
132 
133  register_factory( ReadSmf::factory, WriteSmf::factory, "QSlim format", "smf", "SMF" );
134 
135 #ifdef MOAB_HAVE_NETCDF
136  register_factory( NULL, WriteSLAC::factory, "SLAC", "slac", "SLAC" );
137 #endif
138 
139 #ifdef MOAB_HAVE_CCMIO
140  const char* ccmio_sufxs[] = { "ccm", "ccmg", NULL };
141  register_factory( ReadCCMIO::factory, WriteCCMIO::factory, "CCMIO files", ccmio_sufxs, "CCMIO" );
142 #endif
143 
144 #ifdef MOAB_HAVE_DAMSEL
145  const char* damsel_sufxs[] = { "h5", NULL };
146  register_factory( ReadDamsel::factory, WriteDamsel::factory, "Damsel files", damsel_sufxs, "DAMSEL" );
147 #endif
148 
149  register_factory( NULL, WriteGMV::factory, "GMV", "gmv", "GMV" );
150 
151  register_factory( NULL, WriteAns::factory, "Ansys", "ans", "ANSYS" );
152 
153  const char* gmsh_sufxs[] = { "msh", "gmsh", NULL };
154  register_factory( ReadGmsh::factory, WriteGmsh::factory, "Gmsh mesh file", gmsh_sufxs, "GMSH" );
155 
156  register_factory( ReadSTL::factory, WriteSTL::factory, "Stereo Lithography File (STL)", "stl", "STL" );
157 
158  const char* tetgen_sufxs[] = { "node", "ele", "face", "edge", NULL };
159  register_factory( ReadTetGen::factory, 0, "TetGen output files", tetgen_sufxs, "TETGEN" );
160 
161  const char* template_sufxs[] = { NULL };
162  register_factory( ReadTemplate::factory, WriteTemplate::factory, "Template input files", template_sufxs,
163  "TEMPLATE" );
164 }
165 
167 
169  writer_factory_t writer,
170  const char* description,
171  const char* const* extensions,
172  const char* name )
173 {
174  if( !reader && !writer ) return MB_FAILURE;
175 
176  // check for duplicate names
177  iterator h = handler_by_name( name );
178  if( h != end() )
179  {
180  MB_SET_ERR( MB_FAILURE, "Conflicting string name for file formats: \"" << name << "\"" );
181  }
182 
183  // count extensions and check for duplicates
184  const char* const* iter;
185  for( iter = extensions; *iter; ++iter )
186  {
187  h = handler_from_extension( *iter );
188  if( h != end() )
189  {
190  if( NULL != reader && h->have_reader() )
191  MB_SET_ERR( MB_FAILURE, "Conflicting readers for file extension \""
192  << *iter << "\": \"" << h->description() << "\" and \"" << description
193  << "\"." );
194  else if( NULL != writer && h->have_writer() )
195  MB_SET_ERR( MB_FAILURE, "Conflicting writers for file extension \""
196  << *iter << "\": \"" << h->description() << "\" and \"" << description
197  << "\"." );
198  }
199  }
200  handlerList.push_back( Handler( reader, writer, name, description, extensions, iter - extensions ) );
201  return MB_SUCCESS;
202 }
203 
205  writer_factory_t writer,
206  const char* description,
207  const char* extension,
208  const char* name )
209 {
210  const char* extensions[2] = { extension, NULL };
211  return register_factory( reader, writer, description, extensions, name );
212 }
213 
214 ReaderIface* ReaderWriterSet::get_file_extension_reader( const std::string& filename ) const
215 {
216  std::string ext = extension_from_filename( filename );
217  iterator handler = handler_from_extension( ext, true, false );
218  return handler == end() ? NULL : handler->make_reader( mbCore );
219 }
220 
221 WriterIface* ReaderWriterSet::get_file_extension_writer( const std::string& filename ) const
222 {
223  std::string ext = extension_from_filename( filename );
224  iterator handler = handler_from_extension( ext, false, true );
225  return handler == end() ? NULL : handler->make_writer( mbCore );
226 }
227 
228 std::string ReaderWriterSet::extension_from_filename( const std::string& filename )
229 {
230  std::string::size_type idx = filename.find_last_of( "." );
231  std::string::size_type idirx = filename.find_last_of( "\\/" );
232 
233  if( idx == std::string::npos ) return std::string( "" );
234  if( ( idirx != std::string::npos ) && ( idirx > idx ) ) return std::string( "" );
235  return filename.substr( idx + 1 );
236 }
237 
238 ReaderWriterSet::Handler::Handler( reader_factory_t read_f,
239  writer_factory_t write_f,
240  const char* nm,
241  const char* desc,
242  const char* const* ext,
243  int num_ext )
244  : mReader( read_f ), mWriter( write_f ), mName( nm ), mDescription( desc ), mExtensions( num_ext )
245 {
246  for( int i = 0; i < num_ext; ++i )
247  mExtensions[i] = ext[i];
248 }
249 
250 #ifdef WIN32
251 #define strcasecmp( A, B ) _stricmp( A, B )
252 #endif
253 
255  bool with_reader,
256  bool with_writer ) const
257 {
258  iterator iter;
259  std::vector< std::string >::const_iterator siter;
260 
261  // try case-sensitive compare
262  for( iter = begin(); iter != end(); ++iter )
263  {
264  if( ( with_reader && !iter->have_reader() ) || ( with_writer && !iter->have_writer() ) ) continue;
265 
266  for( siter = iter->mExtensions.begin(); siter != iter->mExtensions.end(); ++siter )
267  if( *siter == ext ) return iter;
268  }
269 
270  // try case-insensitive compare
271  for( iter = begin(); iter != end(); ++iter )
272  {
273  if( ( with_reader && !iter->have_reader() ) || ( with_writer && !iter->have_writer() ) ) continue;
274 
275  for( siter = iter->mExtensions.begin(); siter != iter->mExtensions.end(); ++siter )
276  if( 0 == strcasecmp( siter->c_str(), ext.c_str() ) ) return iter;
277  }
278 
279  return end();
280 }
281 
282 bool ReaderWriterSet::Handler::reads_extension( const char* ext ) const
283 {
284  if( !have_reader() ) return false;
285 
286  std::vector< std::string >::const_iterator siter;
287  for( siter = mExtensions.begin(); siter != mExtensions.end(); ++siter )
288  if( !( *siter ).compare( ext ) )
289  return true;
290  else if( 0 == strcasecmp( siter->c_str(), ext ) )
291  return true;
292 
293  return false;
294 }
295 
296 bool ReaderWriterSet::Handler::writes_extension( const char* ext ) const
297 {
298  if( !have_writer() ) return false;
299 
300  std::vector< std::string >::const_iterator siter;
301  for( siter = mExtensions.begin(); siter != mExtensions.end(); ++siter )
302  if( !( *siter ).compare( ext ) )
303  return true;
304  else if( 0 == strcasecmp( siter->c_str(), ext ) )
305  return true;
306 
307  return false;
308 }
309 
311 {
312  return std::find( begin(), end(), nm );
313 }
314 
315 bool ReaderWriterSet::Handler::operator==( const char* nm ) const
316 {
317  // do case-insensitive comparison
318  std::string::const_iterator siter = mName.begin();
319  for( ; *nm; ++nm, ++siter )
320  if( siter == mName.end() || tolower( *nm ) != tolower( *siter ) ) return false;
321  return *nm == '\0';
322 }
323 
324 } // namespace moab