[MOAB-dev] r2627 - MOAB/trunk

kraftche at mcs.anl.gov kraftche at mcs.anl.gov
Tue Feb 3 15:48:55 CST 2009


Author: kraftche
Date: 2009-02-03 15:48:54 -0600 (Tue, 03 Feb 2009)
New Revision: 2627

Added:
   MOAB/trunk/ReadTetGen.cpp
   MOAB/trunk/ReadTetGen.hpp
Modified:
   MOAB/trunk/Makefile.am
Log:
read tetget output files

Modified: MOAB/trunk/Makefile.am
===================================================================
--- MOAB/trunk/Makefile.am	2009-02-03 19:33:44 UTC (rev 2626)
+++ MOAB/trunk/Makefile.am	2009-02-03 21:48:54 UTC (rev 2627)
@@ -164,6 +164,8 @@
   ReadVtk.hpp \
   ReadIDEAS.cpp \
   ReadIDEAS.hpp \
+  ReadTetGen.cpp \
+  ReadTetGen.hpp \
   ScdElementData.cpp \
   ScdElementData.hpp \
   ScdVertexData.cpp \

Added: MOAB/trunk/ReadTetGen.cpp
===================================================================
--- MOAB/trunk/ReadTetGen.cpp	                        (rev 0)
+++ MOAB/trunk/ReadTetGen.cpp	2009-02-03 21:48:54 UTC (rev 2627)
@@ -0,0 +1,471 @@
+#include "ReadTetGen.hpp"
+#include "MBInterface.hpp"
+#include "MBRange.hpp"
+#include "MBReadUtilIface.hpp"
+#include "FileOptions.hpp"
+#include "MBTagConventions.hpp"
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <ctype.h>
+#include <map>
+
+MBReaderIface* ReadTetGen::factory( MBInterface* moab )
+  { return new ReadTetGen(moab); }
+
+ReadTetGen::ReadTetGen( MBInterface* moab )
+  : mbIface(moab), readTool(0)
+{
+  void* tool_ptr = 0;
+  MBErrorCode rval = moab->query_interface( "MBReadUtilIface", &tool_ptr );
+  if (MB_SUCCESS == rval)
+    readTool = reinterpret_cast<MBReadUtilIface*>(tool_ptr);
+}
+
+ReadTetGen::~ReadTetGen()
+{
+  if (mbIface && readTool)
+    mbIface->release_interface( "MBReadUtilIface", readTool );
+}
+
+MBErrorCode ReadTetGen::open_file( const std::string& filename,
+                                   const std::string& basename,
+                                   const std::string& suffix,
+                                   const char* exp_suffix,
+                                   const char* opt_name,
+                                   const FileOptions& opts,
+                                   std::ifstream& file_stream,
+                                   bool file_required )
+{
+  std::string real_file_name;
+  MBErrorCode rval = opts.get_option( opt_name, real_file_name );
+  if (MB_ENTITY_NOT_FOUND == rval || real_file_name.empty()) {
+    if (MB_SUCCESS == rval)
+      file_required = true;
+    if (suffix == exp_suffix) {
+      real_file_name = filename;
+    }
+    else {
+      real_file_name = basename;
+      real_file_name += ".";
+      real_file_name += exp_suffix;
+    }
+  }
+  
+  if (!real_file_name.empty()) 
+    file_stream.open( real_file_name.c_str(), std::ios::in );
+  if (file_required && !file_stream.is_open()) {
+    readTool->report_error( "%s: cannot read file.", real_file_name.c_str() );
+    return MB_FILE_DOES_NOT_EXIST;
+  }
+  return MB_SUCCESS;
+}
+
+MBErrorCode ReadTetGen::load_file( const char* file_name_c,
+                                   MBEntityHandle& file_set,
+                                   const FileOptions& opts,
+                                   const int*, int )
+{
+  std::ifstream node_file, ele_file, face_file, edge_file;
+  MBErrorCode rval;
+  
+  std::string suffix, base, filename(file_name_c);
+  size_t dot_idx = filename.find_last_of( '.' );
+  if (dot_idx == std::string::npos) {
+    base = filename;
+  }
+  else {
+    suffix = filename.substr( dot_idx+1 );
+    for (size_t i = 0; i < suffix.length(); ++i)
+      suffix[i] = tolower(suffix[i]);
+    if (suffix == "node" || suffix == "ele" || suffix == "face" || suffix == "edge") {
+      base = filename.substr( 0, dot_idx );
+    }
+    else {
+      base = filename;
+      suffix.clear();
+    }
+  }
+  
+  rval = open_file( filename, base, suffix, "node", "NODE_FILE", opts, node_file, true );
+  if (MB_SUCCESS != rval)
+    return rval;
+  rval = open_file( filename, base, suffix, "ele", "ELE_FILE", opts, ele_file );
+  if (MB_SUCCESS != rval)
+    return rval;
+  rval = open_file( filename, base, suffix, "face", "FACE_FILE", opts, face_file );
+  if (MB_SUCCESS != rval)
+    return rval;
+  rval = open_file( filename, base, suffix, "edge", "EDGE_FILE", opts, edge_file );
+  if (MB_SUCCESS != rval)
+    return rval;
+  
+  std::vector<MBTag> attr_tags[4];
+  std::vector<int> attr_idx[4];
+  const char* option_names[4] = { "NODE_ATTR_LIST", "EDGE_ATTR_LIST", "TRI_ATTR_LIST", "TET_ATTR_LIST" };
+  const char* group_names[4] = { 0, "CURVE_ID", "SURFACE_ID", "VOLUME_ID" };
+  for (int i = 0; i < 4; ++i) {
+    std::string opt_str;
+    rval = opts.get_str_option( option_names[i], opt_str );
+    if (MB_SUCCESS != rval)
+      continue;
+    rval = parse_attr_list( opt_str, attr_tags[i], attr_idx[i], group_names[i] );
+    if (MB_SUCCESS != rval) {
+      readTool->report_error( "%s: invalid option value.", option_names[i] );
+      return MB_TYPE_OUT_OF_RANGE;
+    }
+  }
+  
+  MBRange tets, tris, edges;
+  std::vector<MBEntityHandle> nodes;
+  rval = read_node_file( node_file, &attr_tags[0][0], &attr_idx[0][0], attr_tags[0].size(), nodes );
+  if (MB_SUCCESS == rval && ele_file.is_open())
+    rval = read_elem_file( MBTET, ele_file, nodes, tets );
+  if (MB_SUCCESS == rval && face_file.is_open())
+    rval = read_elem_file( MBTRI, face_file, nodes, tris );
+  if (MB_SUCCESS == rval && edge_file.is_open())
+    rval = read_elem_file( MBEDGE, edge_file, nodes, edges );
+
+  file_set = 0;
+  if (MB_SUCCESS == rval)
+    rval = mbIface->create_meshset( MESHSET_SET, file_set );
+  if (MB_SUCCESS == rval)
+    rval = mbIface->add_entities( file_set, &nodes[0], nodes.size() );
+  if (MB_SUCCESS == rval)
+    rval = mbIface->add_entities( file_set, tets );
+  if (MB_SUCCESS == rval)
+    rval = mbIface->add_entities( file_set, tris );
+  if (MB_SUCCESS == rval)
+    rval = mbIface->add_entities( file_set, edges );
+  
+  if (MB_SUCCESS != rval) {
+    if (file_set) 
+      mbIface->delete_entities( &file_set, 1 );
+    mbIface->delete_entities( tets );
+    mbIface->delete_entities( tris );
+    mbIface->delete_entities( edges );
+    mbIface->delete_entities( &nodes[0], nodes.size() );
+  }
+  
+  return rval;  
+}
+
+MBErrorCode ReadTetGen::parse_attr_list( const std::string& option_str,
+                                         std::vector<MBTag>& tag_list,
+                                         std::vector<int>& index_list,
+                                         const char* group_designator )
+{
+  std::vector<std::string> name_list;
+  size_t prev_pos = 0;
+  while (prev_pos != std::string::npos) {
+    size_t pos = option_str.find_first_of( ',', prev_pos );
+    name_list.push_back( option_str.substr( prev_pos, pos ) );
+    prev_pos = pos+1; 
+  }
+
+  index_list.resize( name_list.size() );
+  std::map<std::string,int> name_count;
+  for (size_t i = 0; i < name_list.size(); ++i)
+    index_list[i] = name_count[name_list[i]]++;
+
+  for (size_t i = 0; i < name_list.size(); ++i) {
+    if (group_designator && name_list[i] == group_designator) {
+      tag_list[i] = 0;
+      index_list[i] = -1;
+    }
+    else if (name_list.empty()) {
+      tag_list[i] = 0;
+      index_list[i] = 0;
+    }
+    else {
+      MBErrorCode rval = mbIface->tag_create( name_list[i].c_str(),
+                                  name_count[name_list[i]]*sizeof(double),
+                                  MB_TAG_DENSE,
+                                  MB_TYPE_DOUBLE,
+                                  tag_list[i],
+                                  0,
+                                  true );
+      if (MB_SUCCESS != rval)
+        return rval;
+    }
+  }
+  
+  return MB_SUCCESS;
+}
+
+MBErrorCode ReadTetGen::read_line( std::istream& file,
+                                   std::string& line,
+                                   int& lineno )
+{
+    // loop until we find a non-empty line
+  do {
+      // read a line
+    line.clear();
+    if (!getline( file, line )) 
+      return MB_FILE_WRITE_ERROR;
+    ++lineno;
+      // strip comments from line
+    size_t pos = line.find_first_of( '#' );
+    if (pos != std::string::npos)
+      line = line.substr( 0, pos );
+      // strip leading whitespace from line
+    for (pos = 0; pos < line.length() && isspace(line[pos]); ++pos);
+    if (pos == line.length())
+      line.clear();
+    else if (pos != 0)
+      line = line.substr( pos );
+  } while (line.empty());
+  
+  return MB_SUCCESS;  
+}
+
+MBErrorCode ReadTetGen::read_line( std::istream& file,
+                                   double* values_out,
+                                   int num_values, 
+                                   int& lineno )
+{
+    // get a line of text
+  std::string line;
+  MBErrorCode rval = read_line( file, line, lineno );
+  if (MB_SUCCESS != rval)
+    return rval;
+  
+    // tokenize line as doubles
+  std::stringstream str(line);
+  for (int i = 0; i < num_values; ++i) {
+    double v;
+    if (!(str >> v)) {
+      readTool->report_error( "Error reading node data at line %d.", lineno );
+      return MB_FAILURE;
+    }
+    values_out[i] = v;
+  }
+  
+    // check that we're at the end of the line
+  int junk;
+  if ((str >> junk) || !str.eof()) {
+    readTool->report_error( "Unexpected trailing data for line %d of node data", lineno );
+    return MB_FAILURE;
+  }
+  
+  return MB_SUCCESS;
+}
+
+MBErrorCode ReadTetGen::read_node_file( std::istream& file, 
+                                        const MBTag* attr_tag_list,
+                                        const int* attr_tag_index,
+                                        int attr_tag_list_len,
+                                        std::vector<MBEntityHandle>& nodes )
+{
+  int lineno = 0;
+  std::string line;
+  MBErrorCode rval;
+  
+  double header_vals[4];
+  rval = read_line( file, header_vals, 4, lineno );
+  if (MB_SUCCESS != rval)
+    return rval;
+  
+  const int num_vtx = (int)header_vals[0];
+  const int dim = (int)header_vals[1];
+  const int num_attr = (int)header_vals[2];
+  const int bdry_flag = (int)header_vals[3];
+  if (num_vtx < 1 || dim < 2 || dim > 3 || num_attr < 0 || bdry_flag < 0 || bdry_flag > 1) {
+    readTool->report_error( "Invalid header line for node data." );
+    return MB_FAILURE;
+  }
+  if (attr_tag_list_len > num_attr)
+    attr_tag_list_len = num_attr;
+  
+    // allocate space for tag data
+  std::map< MBTag, int > tag_size;
+  std::map< MBTag, std::vector<double> > tag_data;
+  for (int i = 0; i < attr_tag_list_len; ++i) {
+    if (!attr_tag_list[i] || attr_tag_index[i] < 0)
+      continue;
+    std::vector<double>& data = tag_data[attr_tag_list[i]];
+      // increase tag size by one value per vertex for each time
+      // we encounter it in the list.
+    data.resize( data.size() + num_vtx );
+    ++tag_size[attr_tag_list[i]];
+  }
+  std::vector<double*> attr_data( attr_tag_list_len );
+  std::vector<int> attr_size( attr_tag_list_len );
+  for (int i = 0; i < attr_tag_list_len; ++i) {
+    if (!attr_tag_list[i] || attr_tag_index[i] < 0) {
+      attr_data[i] = 0;
+      attr_size[i] = 0;
+    }
+    else {
+      attr_data[i] = &(tag_data[attr_tag_list[i]])[0];
+      attr_size[i] = tag_size[attr_tag_list[i]];
+    }
+  }
+  
+    // allocate vertices
+  std::vector<double*> coords;
+  MBEntityHandle start_handle;
+  rval = readTool->get_node_arrays( dim, num_vtx, 1, start_handle, coords );
+  if (MB_SUCCESS != rval)
+    return rval;
+  
+    // read data line for each node
+  nodes.reserve( num_vtx );
+  std::vector<double> data( 1 + dim + num_attr + bdry_flag );
+  std::vector<int> ids(num_vtx);
+  for (int i = 0; i < num_vtx; ++i) {
+    rval = read_line( file, &data[0], data.size(), lineno );
+    if (MB_SUCCESS != rval)
+      return rval;
+    
+      // get ID
+    ids[i] = (int)data[0];
+    if (ids[i] >= (int)nodes.size())
+      nodes.resize( ids[i] + 1 );
+    nodes[ids[i]] = start_handle + i;
+    
+      // get coordiantes
+    for (int j = 0; j < dim; ++j)
+      coords[j][i] = data[j+1];
+  
+      // get attribute data
+    for (int j = 0; j < attr_tag_list_len; ++j)
+      if (attr_data[j])
+        attr_data[j][i*attr_size[j]+attr_tag_index[j]] = data[j+1+dim];
+    
+      // disgard boundary bit
+  }
+  
+    // store tag data
+  MBRange node_range;
+  node_range.insert( start_handle, start_handle + num_vtx - 1 );
+  for (std::map< MBTag, std::vector<double> >::iterator i = tag_data.begin();
+       i != tag_data.end(); ++i) {
+    rval = mbIface->tag_set_data( i->first, node_range, &i->second[0] );
+    if (MB_SUCCESS != rval)
+      return rval;
+  }
+  MBTag idtag;
+  rval = mbIface->tag_get_handle( GLOBAL_ID_TAG_NAME, idtag );
+  if (MB_SUCCESS == rval) {
+    rval = mbIface->tag_set_data( idtag, node_range, &ids[0] );
+    if (MB_SUCCESS != rval)
+      return rval;
+  }
+  
+  return MB_SUCCESS;
+}
+  
+
+MBErrorCode ReadTetGen::read_elem_file( MBEntityType type,
+                                        std::istream& file, 
+                                        const std::vector<MBEntityHandle>& nodes,
+                                        MBRange& elems )
+{
+  int lineno = 0;
+  std::string line;
+  MBErrorCode rval;
+  
+  int node_per_elem, have_group_id, dim;
+  double header_vals[3];
+  switch (type) {
+    case MBTET:
+      rval = read_line( file, header_vals, 3, lineno );
+      node_per_elem = (int)header_vals[1];
+      have_group_id = (int)header_vals[2];
+      dim = 3;
+      break;
+    case MBTRI:
+      rval = read_line( file, header_vals, 2, lineno );
+      node_per_elem = 3;
+      have_group_id = (int)header_vals[1];
+      dim = 2;
+      break;
+    case MBEDGE:
+      rval = read_line( file, header_vals, 1, lineno );
+      node_per_elem = 2;
+      have_group_id = 0;
+      dim = 1;
+      break;
+    default:
+      rval = MB_FAILURE;
+      break;
+  }
+  if (MB_SUCCESS != rval)
+    return rval;
+  const int num_elem = (int)header_vals[0];
+  if (num_elem < 1 || node_per_elem < 2 || have_group_id < 0 || have_group_id > 1) {
+    readTool->report_error( "Invalid header line for element data." );
+    return MB_FAILURE;
+  }
+  
+    // create group map
+  std::map<double,MBEntityHandle> groups;
+  MBTag dim_tag, id_tag;
+  rval = mbIface->tag_get_handle( GLOBAL_ID_TAG_NAME, id_tag );
+  if (MB_SUCCESS != rval)
+    return rval;
+  rval = mbIface->tag_create( GEOM_DIMENSION_TAG_NAME, sizeof(int),
+                             MB_TAG_SPARSE, MB_TYPE_INTEGER, dim_tag,
+                             0, true );
+  if (MB_SUCCESS != rval)
+    return rval;
+    
+  
+    // allocate elements
+  MBEntityHandle start_handle, *conn_array;
+  rval = readTool->get_element_array( num_elem, node_per_elem, type, 1, start_handle, conn_array );
+  if (MB_SUCCESS != rval)
+    return rval;
+  elems.insert( start_handle, start_handle + num_elem - 1 );
+  
+    // read data line for each node
+  std::vector<double> data( 1 + node_per_elem + have_group_id );
+  std::vector<int> ids(num_elem);
+  for (int i = 0; i < num_elem; ++i) {
+    rval = read_line( file, &data[0], data.size(), lineno );
+    if (MB_SUCCESS != rval)
+      return rval;
+    
+      // get ID
+    ids[i] = (int)data[0];
+    
+      // get connectivity
+    for (int j = 0; j < node_per_elem; ++j)
+      conn_array[node_per_elem*i+j] = nodes[data[j+1]];
+  
+      // grouping
+    if (have_group_id && 0.0 != data[node_per_elem+1]) {
+      double id = data[node_per_elem+1];
+      MBEntityHandle grp = groups[id];
+      if (0 == grp) {
+        rval = mbIface->create_meshset( MESHSET_SET, grp );
+        if (MB_SUCCESS != rval)
+          return rval;
+        elems.insert( grp );
+        rval = mbIface->tag_set_data( dim_tag, &grp, 1, &dim );
+        if (MB_SUCCESS != rval)
+          return rval;
+        int iid = (int)id;
+        rval = mbIface->tag_set_data( id_tag, &grp, 1, &iid );
+        if (MB_SUCCESS != rval)
+          return rval;
+        groups[id] = grp;
+      }
+      MBEntityHandle handle = start_handle + i;
+      rval = mbIface->add_entities( grp, &handle, 1 );
+      if (MB_SUCCESS != rval)
+        return rval;
+    }
+  }
+  
+    // store id data
+  MBRange elems2;
+  elems2.insert( start_handle, start_handle + num_elem - 1 );
+  rval = mbIface->tag_set_data( id_tag, elems2, &ids[0] );
+  if (MB_SUCCESS != rval)
+    return rval;
+  
+  return MB_SUCCESS;
+}
+  

Added: MOAB/trunk/ReadTetGen.hpp
===================================================================
--- MOAB/trunk/ReadTetGen.hpp	                        (rev 0)
+++ MOAB/trunk/ReadTetGen.hpp	2009-02-03 21:48:54 UTC (rev 2627)
@@ -0,0 +1,129 @@
+#ifndef READ_TET_GEN_HPP
+#define READ_TET_GEN_HPP
+
+#include <iosfwd>
+#include "MBForward.hpp"
+#include "MBReaderIface.hpp"
+class MBReadUtilIface;
+
+/* TetGen mesh data is typically split into two or three files:
+ * name.node : node data
+ * name.ele  : tet data
+ * name.face : tri data
+ * The reader will attempt to guess the correct file names from
+ * the single input file name unless explicit file names are
+ * specified using file options as described below.
+ *
+ * File options:
+ *   NODE_FILE=filename   : node file name
+ *   ELE_FILE[=filename]  : require tet file and optionally specify file name
+ *   FACE_FILE[=filename] : reequire tri file and optionally specify file name
+ *   EDGE_FILE[=filename] : reequire edge file and optionally specify file name
+ *   NODE_ATTR_LIST=name[,name[,...]] : List of tag names in which to store
+ *                                     attribute values.  If the same name
+ *                                     is repeated multiple times, multiple
+ *                                     attribute values will be stored in the
+ *                                     same tag as array values in the order
+ *                                     they are read from the file.  If a 
+ *                                     name is zero-length, the attribute data
+ *                                     will be disgarded.  
+ */
+class ReadTetGen : public MBReaderIface
+{
+   
+public:
+
+  static MBReaderIface* factory( MBInterface* );
+
+    //! load a file
+  MBErrorCode load_file(const char *file_name,
+                        MBEntityHandle& file_set,
+                        const FileOptions&,
+                        const int* material_set_list,
+                        int num_material_sets );
+  
+    //! Constructor
+  ReadTetGen(MBInterface* impl = NULL);
+
+   //! Destructor
+  virtual ~ReadTetGen();
+
+private:
+
+  MBInterface* mbIface;
+  MBReadUtilIface* readTool;
+
+  /**\brief Try to open one of several input files
+   *
+   *\param input_file_name  The file name as passed in by the application
+   *\param input_name_base  If the input file name ends with a known suffix,
+   *                        the portition of the input file without the suffix.
+   *                        Otherwise equal to input_file_name.
+   *\param input_file_suffix If the input file name ends with a known suffix,
+   *                        the suffix.  Otherwise empty.
+   *\param file_type_suffix The suffix for the file type that is to be opened.
+   *\param file_name_option The FileOptions option name specifying the file
+   *                        name to open.
+   *\param opts             Input options list.
+   *\param file_stream      The stream to open for the file.
+   */
+  MBErrorCode open_file( const std::string& input_file_name,
+                         const std::string& input_name_base,
+                         const std::string& input_name_suffix,
+                         const char* file_type_suffix,
+                         const char* file_name_option,
+                         const FileOptions& opts,
+                         std::ifstream& file_stream,
+                         bool file_required = false );
+
+  /**\brief Read a line from a file
+   * 
+   * Read the next non-empty line.  Strips comments.
+   *\param file   The stream to read from
+   *\param line   Output: the line read from the stream
+   *\param lineno Incremented for each real line read from the stream
+   *              (including disgarded empty and comment lines.)
+   */
+  MBErrorCode read_line( std::istream& file, std::string& line, int& lineno );
+
+  /**\brief Read a line of double values from a file.
+   */
+  MBErrorCode read_line( std::istream& file, 
+                         double* values_out, int num_values,
+                         int& lineno );
+
+  /**\brief Parse option string specifying mapping from 
+   *        attributes to tags.
+   *
+   * Given a file option string describing the mapping from tetgen
+   * attributes to MOAB tags, parse it and populate the passed vectors.
+   * \param option_str  Input: The option string to parse.
+   * \param tag_list    Output: A list tag handles, one for each attribute.
+   *                    Tag handle value will be zero if the attribute
+   *                    is to be interpreted as a group id.
+   * \param index_list  Output: Which array index to store the attribute
+   *                    value at for a multi-valued tag.  Zero for single-
+   *                    valued tags.  -1 if the corresponding attribute value
+   *                    is to be interpreted as a group ID.
+   * \param group_designator Input: special tag name used to designate an
+   *                    attribute as the group (surface or volume) ID.
+   */
+  MBErrorCode parse_attr_list( const std::string& option_str,
+                               std::vector<MBTag>& tag_list,
+                               std::vector<int>& index_list,
+                               const char* group_designator = 0 );
+
+  MBErrorCode read_node_file( std::istream& file, 
+                              const MBTag* attr_tag_list,
+                              const int* attr_tag_index,
+                              int attr_tag_list_len,
+                              std::vector<MBEntityHandle>& nodes );
+
+  MBErrorCode read_elem_file( MBEntityType type,
+                              std::istream& file, 
+                              const std::vector<MBEntityHandle>& nodes,
+                              MBRange& elems );
+};
+
+
+#endif // defined(READ_TET_GEN_HPP)



More information about the moab-dev mailing list