Beispiel #1
0
    ErrorCode LinearHex::normalFcn(const int ientDim, const int facet, const int nverts, const double *verts,  double normal[3])
    {
      //assert(facet < 6 && ientDim == 2 && nverts == 8);
      if (nverts != 8)
        MB_SET_ERR(MB_FAILURE, "Incorrect vertex count for passed hex :: expected value = 8 ");
      if (ientDim != 2)
        MB_SET_ERR(MB_FAILURE, "Requesting normal for unsupported dimension :: expected value = 2 ");
      if (facet >6 || facet < 0)
        MB_SET_ERR(MB_FAILURE, "Incorrect local face id :: expected value = one of 0-5");

      int id0 = CN::mConnectivityMap[MBHEX][ientDim-1].conn[facet][0];
      int id1 = CN::mConnectivityMap[MBHEX][ientDim-1].conn[facet][1];
      int id2 = CN::mConnectivityMap[MBHEX][ientDim-1].conn[facet][3];

      double x0[3], x1[3];

      for (int i=0; i<3; i++)
        {
          x0[i] = verts[3*id1+i] - verts[3*id0+i];
          x1[i] = verts[3*id2+i] - verts[3*id0+i];
        }

      double a = x0[1]*x1[2] - x1[1]*x0[2];
      double b = x1[0]*x0[2] - x0[0]*x1[2];
      double c = x0[0]*x1[1] - x1[0]*x0[1];
      double nrm = sqrt(a*a+b*b+c*c);

      if (nrm > std::numeric_limits<double>::epsilon()) {
          normal[0] = a/nrm;
          normal[1] = b/nrm;
          normal[2] = c/nrm;
        }
      return MB_SUCCESS;
    }
Beispiel #2
0
ErrorCode ReadNC::get_dimensions(int file_id, std::vector<std::string>& dim_names, std::vector<int>& dim_lens)
{
  // Get the number of dimensions
  int num_dims;
  int success = NCFUNC(inq_ndims)(file_id, &num_dims);
  if (success)
    MB_SET_ERR(MB_FAILURE, "Trouble getting number of dimensions");

  if (num_dims > NC_MAX_DIMS) {
    MB_SET_ERR(MB_FAILURE, "ReadNC: File contains " << num_dims << " dims but NetCDF library supports only " << NC_MAX_DIMS);
  }

  char dim_name[NC_MAX_NAME + 1];
  NCDF_SIZE dim_len;
  dim_names.resize(num_dims);
  dim_lens.resize(num_dims);

  for (int i = 0; i < num_dims; i++) {
    success = NCFUNC(inq_dim)(file_id, i, dim_name, &dim_len);
    if (success)
      MB_SET_ERR(MB_FAILURE, "Trouble getting dimension info");

    dim_names[i] = std::string(dim_name);
    dim_lens[i] = dim_len;

    dbgOut.tprintf(2, "Dimension %s, length=%u\n", dim_name, (unsigned int) dim_len);
  }

  return MB_SUCCESS;
}
Beispiel #3
0
    /** \brief Convert representation from fine to coarse
     * Each element in set, or in interface if set is not input, is converted to coarse elements, with
     * fine vertices put into SPECTRAL_VERTICES tagged array.  NOTE: This function assumes that each
     * order^d (fine) elements comprise each coarse element, and are in order of fine elements in each
     * coarse element.  If order is input as 0, looks for a SPECTRAL_ORDER tag on the mesh.
     * \param order Order of the spectral mesh
     * \param spectral_set Set containing spectral elements
     */
ErrorCode SpectralMeshTool::convert_to_coarse(int order, EntityHandle spectral_set) 
{
  if (order) spectralOrder = order;
  if (!spectralOrder) {
    MB_SET_ERR(MB_FAILURE, "Spectral order must be set or input before converting to spectral mesh");
  }
  
  Range tmp_ents, ents;
  ErrorCode rval = mbImpl->get_entities_by_handle(spectral_set, tmp_ents);
  if (MB_SUCCESS != rval || ents.empty()) return rval;
  
    // get the max-dimensional elements from it
  ents = tmp_ents.subset_by_dimension(3);
  if (ents.empty()) ents = tmp_ents.subset_by_dimension(2);
  if (ents.empty()) ents = tmp_ents.subset_by_dimension(1);
  if (ents.empty()) {
    MB_SET_ERR(MB_FAILURE, "Can't find any entities for conversion");
  }
    
    // get a ptr to connectivity
  if (ents.psize() != 1) {
    MB_SET_ERR(MB_FAILURE, "Entities must be in one chunk for conversion");
  }
  EntityHandle *conn;
  int count, verts_per_e;
  rval = mbImpl->connect_iterate(ents.begin(), ents.end(), conn, verts_per_e, count);
  if (MB_SUCCESS != rval || count != (int)ents.size()) return rval;

  Range tmp_range;
  return create_spectral_elems(conn, ents.size(), CN::Dimension(TYPE_FROM_HANDLE(*ents.begin())), tmp_range);
}
Beispiel #4
0
// Read ASCII file
ErrorCode ReadSTL::ascii_read_triangles(const char* name,
                                        std::vector<ReadSTL::Triangle>& tris)
{
  FILE* file = fopen(name, "r");
  if (!file) {
    MB_SET_ERR(MB_FILE_DOES_NOT_EXIST, name << ": " << strerror(errno));
  }

  char header[81];
  if (!fgets(header, sizeof(header), file) || // Read header line
      strlen(header) < 6                   || // Must be at least 6 chars
      header[strlen(header) - 1] != '\n'   || // Cannot exceed 80 chars
      memcmp(header, "solid", 5)           || // Must begin with "solid"
      !isspace(header[5])) {                  // Followed by a whitespace char
    fclose(file);
    MB_SET_ERR(MB_FILE_WRITE_ERROR, name << ": " << strerror(errno));
  }

  // Use tokenizer for remainder of parsing
  FileTokenizer tokens(file, readMeshIface);

  Triangle tri;
  float norm[3];

  // Read until end of file. If we reach "endsolid", read
  // was successful. If EOF before "endsolid", return error.
  for (;;) {
    // Check for either another facet or the end of the list.
    const char* const expected[] = {"facet", "endsolid", 0};
    switch (tokens.match_token(expected)) {
      case 1:  break;                      // Found another facet
      case 2:  return MB_SUCCESS;          // Found "endsolid" -- done
      default: return MB_FILE_WRITE_ERROR; // Found something else, or EOF
    }

    if (!tokens.match_token("normal") || // Expect "normal" keyword
        !tokens.get_floats(3, norm)   || // Followed by normal vector
        !tokens.match_token("outer")  || // Followed by "outer loop"
        !tokens.match_token("loop"))
      return MB_FILE_WRITE_ERROR;

    // For each of three triangle vertices
    for (int i = 0; i < 3; i++) {
      if (!tokens.match_token("vertex") ||
          !tokens.get_floats(3, tri.points[i].coords))
        return MB_FILE_WRITE_ERROR;
    }

    if (!tokens.match_token("endloop") || // Facet ends with "endloop"
        !tokens.match_token("endfacet"))  // and then "endfacet"
      return MB_FILE_WRITE_ERROR;

    tris.push_back(tri);
  }

  fclose(file);
  return MB_SUCCESS;
}
Beispiel #5
0
ErrorCode ReadNC::read_header()
{
  dbgOut.tprint(1, "Reading header...\n");

  // Get the global attributes
  int numgatts;
  int success;
  success = NCFUNC(inq_natts )(fileId, &numgatts);
  if (success)
    MB_SET_ERR(MB_FAILURE, "Couldn't get number of global attributes");

  // Read attributes into globalAtts
  ErrorCode result = get_attributes(NC_GLOBAL, numgatts, globalAtts);MB_CHK_SET_ERR(result, "Trouble getting global attributes");
  dbgOut.tprintf(1, "Read %u attributes\n", (unsigned int) globalAtts.size());

  // Read in dimensions into dimNames and dimLens
  result = get_dimensions(fileId, dimNames, dimLens);MB_CHK_SET_ERR(result, "Trouble getting dimensions");
  dbgOut.tprintf(1, "Read %u dimensions\n", (unsigned int) dimNames.size());

  // Read in variables into varInfo
  result = get_variables();MB_CHK_SET_ERR(result, "Trouble getting variables");
  dbgOut.tprintf(1, "Read %u variables\n", (unsigned int) varInfo.size());

  return MB_SUCCESS;
}
Beispiel #6
0
ErrorCode WriteVtk::write_file(const char *file_name,
                               const bool overwrite,
                               const FileOptions& opts,
                               const EntityHandle *output_list,
                               const int num_sets,
                               const std::vector<std::string>& /* qa_list */,
                               const Tag* tag_list,
                               int num_tags,
                               int /* export_dimension */)
{
  ErrorCode rval;

  // Get precision for node coordinates
  int precision;
  if (MB_SUCCESS != opts.get_int_option("PRECISION", precision))
    precision = DEFAULT_PRECISION;

  if (MB_SUCCESS == opts.get_null_option("STRICT"))
    mStrict = true;
  else if (MB_SUCCESS == opts.get_null_option("RELAXED"))
    mStrict = false;
  else
    mStrict = DEFAULT_STRICT;

  // Get entities to write
  Range nodes, elems;
  rval = gather_mesh(output_list, num_sets, nodes, elems);
  if (MB_SUCCESS != rval)
    return rval;

  // Honor overwrite flag
  if (!overwrite) {
    rval = writeTool->check_doesnt_exist(file_name);
    if (MB_SUCCESS != rval)
      return rval;
  }

  // Create file
  std::ofstream file(file_name);
  if (!file) {
    MB_SET_ERR(MB_FILE_WRITE_ERROR, "Could not open file: " << file_name);
  }
  file.precision(precision);

  // Write file
  if ((rval = write_header(file              )) != MB_SUCCESS ||
      (rval = write_nodes( file, nodes       )) != MB_SUCCESS ||
      (rval = write_elems( file, nodes, elems)) != MB_SUCCESS ||
      (rval = write_tags ( file, true,  nodes, tag_list, num_tags)) != MB_SUCCESS ||
      (rval = write_tags ( file, false, elems, tag_list, num_tags)) != MB_SUCCESS) {
    file.close();
    remove(file_name);
    return rval;
  }

  return MB_SUCCESS;
}
Beispiel #7
0
ErrorCode MeshTag::get_data(const SequenceManager*,
                            Error* /* error */,
                            const Range& r,
                            void*) const
{
  if (variable_length()) {
    MB_SET_ERR(MB_VARIABLE_DATA_LENGTH, "No length specified for variable-length tag " << get_name() << " value");
  }
  else if (r.empty())
    return MB_SUCCESS;
  else
    return not_root_set(get_name(), r.front());
}
Beispiel #8
0
ErrorCode WriteVtk::write_bit_tag(std::ostream& stream,
                                  Tag tag,
                                  const Range& entities,
                                  const Range& tagged)
{
  ErrorCode rval;
  const unsigned long n = entities.size();

  // Get tag properties

  std::string name;
  int vals_per_tag;
  if (MB_SUCCESS != mbImpl->tag_get_name(tag, name) ||
      MB_SUCCESS != mbImpl->tag_get_length(tag, vals_per_tag))
    return MB_FAILURE;

  if (vals_per_tag > 8) {
    MB_SET_ERR(MB_FAILURE, "Invalid tag size for bit tag \"" << name << "\"");
  }

  // Get a tag value for each entity.
  // Get bits for each entity and unpack into
  // one integer in the 'data' array for each bit.
  // Initialize 'data' to zero because we will skip
  // those entities for which the tag is not set.
  std::vector<unsigned short> data;
  data.resize(n * vals_per_tag, 0);
  Range::const_iterator t = tagged.begin();
  std::vector<unsigned short>::iterator d = data.begin();
  for (Range::const_iterator i = entities.begin();
       i != entities.end() && t != tagged.end(); ++i) {
    if (*i == *t) {
      ++t;
      unsigned char value;
      rval = mbImpl->tag_get_data(tag, &(*i), 1, &value);
      for (int j = 0; j < vals_per_tag; ++j, ++d)
        *d = (unsigned short)(value & (1 << j) ? 1 : 0);
      if (MB_SUCCESS != rval)
        return rval;
    }
    else {
      // If tag is not set for entity, skip values in array
      d += vals_per_tag;
    }
  }

  // Write the tag values, one entity per line.
  write_data(stream, data, vals_per_tag);

  return MB_SUCCESS;
}
Beispiel #9
0
ErrorCode ReadNC::get_attributes(int var_id, int num_atts, std::map<std::string, AttData>& atts, const char* prefix)
{
  char dum_name[120];

  for (int i = 0; i < num_atts; i++) {
    // Get the name
    int success = NCFUNC(inq_attname)(fileId, var_id, i, dum_name);
    if (success)
      MB_SET_ERR(MB_FAILURE, "Trouble getting attribute name");

    AttData &data = atts[std::string(dum_name)];
    data.attName = std::string(dum_name);
    success = NCFUNC(inq_att)(fileId, var_id, dum_name, &data.attDataType, &data.attLen);
    if (success)
      MB_SET_ERR(MB_FAILURE, "Trouble getting info for attribute " << data.attName);
    data.attVarId = var_id;

    dbgOut.tprintf(2, "%sAttribute %s: length=%u, varId=%d, type=%d\n", (prefix ? prefix : ""), data.attName.c_str(),
        (unsigned int) data.attLen, data.attVarId, data.attDataType);
  }

  return MB_SUCCESS;
}
Beispiel #10
0
ErrorCode RangeSetIterator::get_next_by_dimension(const EntityHandle *&ptr, int count,
                                                  std::vector<EntityHandle> &arr, bool &atend) 
{
    // iterating by dimension - type should be maxtype
  if (entType != MBMAXTYPE) {
    MB_SET_ERR(MB_FAILURE, "Both dimension and type should not be set on an iterator");
  }
    
  unsigned int num_ret = 0;
  size_t idx = 0;
    // initialize to first relevant handle
  while ((int)idx < count &&
         (iterPos > ptr[idx+1] ||
          (!iterPos && entDimension > CN::Dimension(TYPE_FROM_HANDLE(ptr[idx+1])))))
    idx += 2;
  if ((int)idx == count || CN::Dimension(TYPE_FROM_HANDLE(ptr[idx])) > entDimension) {
    atend = true;
    return MB_SUCCESS;
  }
  if (!iterPos) iterPos = ptr[idx];
  else if (CN::Dimension(TYPE_FROM_HANDLE(ptr[idx])) < entDimension)
    iterPos = CREATE_HANDLE(CN::TypeDimensionMap[entDimension].first,1);
  
    // idx points to start of subrange, iterPos in that subrange
  do {
    EntityHandle next = ptr[idx+1];
    if (CN::Dimension(TYPE_FROM_HANDLE(next)) != entDimension) 
      next = LAST_HANDLE(CN::TypeDimensionMap[entDimension].second);
    unsigned int this_ret = chunkSize-num_ret;
    unsigned int to_end = next - iterPos + 1;
    if (to_end < this_ret) this_ret = to_end;
    std::copy(MeshSet::hdl_iter(iterPos), MeshSet::hdl_iter(iterPos + this_ret),
              std::back_inserter(arr));
    if (this_ret == to_end) {
      idx += 2;
      iterPos = ((int)idx < count ? ptr[idx] : 0);
    }
    else iterPos += this_ret;

    num_ret += this_ret;
  }
  while ((int)idx < count && num_ret < chunkSize && 
         iterPos && CN::Dimension(TYPE_FROM_HANDLE(iterPos)) == entDimension);

  if (!iterPos || CN::Dimension(TYPE_FROM_HANDLE(iterPos)) != entDimension) atend = true;

  return MB_SUCCESS;
}
Beispiel #11
0
ErrorCode MeshTag::set_data(SequenceManager*,
                            Error* /* error */,
                            const EntityHandle* entities,
                            size_t num_entities,
                            const void* data)
{
  if (variable_length()) {
    MB_SET_ERR(MB_VARIABLE_DATA_LENGTH, "No length specified for variable-length tag " << get_name() << " value");
  }
  if (!all_root_set(get_name(), entities, num_entities))
    return MB_TAG_NOT_FOUND;

  if (num_entities > 0) {
    mValue.resize(get_size());
    const unsigned char* bytes = reinterpret_cast<const unsigned char*>(data);
    memcpy(&mValue[0], bytes + get_size() * (num_entities - 1), get_size());
  }

  return MB_SUCCESS;
}
Beispiel #12
0
ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *, ScdBox *) 
{
  return MB_FAILURE;
#else
ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *pcomm, ScdBox *box) 
{
  EntityHandle seth = box->box_set();

    // check the # ents in the box against the num in the set, to make sure it's only 1 box;
    // reuse tmp_range
  Range tmp_range;
  ErrorCode rval = mbImpl->get_entities_by_dimension(seth, box->box_dimension(), tmp_range);
  if (MB_SUCCESS != rval) return rval;
  if (box->num_elements() != (int)tmp_range.size()) return MB_FAILURE;
    
  const int *gdims = box->par_data().gDims;
  if ((gdims[0] == gdims[3] && gdims[1] == gdims[4] && gdims[2] == gdims[5]) ||
      -1 == box->par_data().partMethod) return MB_FAILURE;

    // ok, we have a partitioned box; get the vertices shared with other processors
  std::vector<int> procs, offsets, shared_indices;
  rval = get_shared_vertices(pcomm, box, procs, offsets, shared_indices);
  if (MB_SUCCESS != rval) return rval;

    // post receives for start handles once we know how many to look for
  std::vector<MPI_Request> recv_reqs(procs.size(), MPI_REQUEST_NULL), 
      send_reqs(procs.size(), MPI_REQUEST_NULL);
  std::vector<EntityHandle> rhandles(4*procs.size()), shandles(4);
  for (unsigned int i = 0; i < procs.size(); i++) {
    int success = MPI_Irecv(&rhandles[4*i], 4*sizeof(EntityHandle),
                            MPI_UNSIGNED_CHAR, procs[i],
                            1, pcomm->proc_config().proc_comm(), 
                            &recv_reqs[i]);
    if (success != MPI_SUCCESS) return MB_FAILURE;
  }

    // send our own start handles
  shandles[0] = box->start_vertex();
  shandles[1] = 0;
  if (box->box_dimension() == 1) {
    shandles[1] = box->start_element();
    shandles[2] = 0;
    shandles[3] = 0;
  } else if (box->box_dimension() == 2) {
    shandles[2] = box->start_element();
    shandles[3] = 0;
  }
  else {
    shandles[2] = 0;
    shandles[3] = box->start_element();
  }
  for (unsigned int i = 0; i < procs.size(); i++) {
    int success = MPI_Isend(&shandles[0], 4*sizeof(EntityHandle), MPI_UNSIGNED_CHAR, procs[i], 
                            1, pcomm->proc_config().proc_comm(), &send_reqs[i]);
    if (success != MPI_SUCCESS) return MB_FAILURE;
  }
  
    // receive start handles and save info to a tuple list
  int incoming = procs.size();
  int p, j, k;
  MPI_Status status;
  TupleList shared_data;
  shared_data.initialize(1, 0, 2, 0, 
                         shared_indices.size()/2);
  shared_data.enableWriteAccess();

  j = 0; k = 0;
  while (incoming) {
    int success = MPI_Waitany(procs.size(), &recv_reqs[0], &p, &status);
    if (MPI_SUCCESS != success) return MB_FAILURE;
    unsigned int num_indices = (offsets[p+1]-offsets[p])/2;
    int *lh = &shared_indices[offsets[p]], *rh = lh + num_indices;
    for (unsigned int i = 0; i < num_indices; i++) {
      shared_data.vi_wr[j++] = procs[p];
      shared_data.vul_wr[k++] = shandles[0] + lh[i];
      shared_data.vul_wr[k++] = rhandles[4*p] + rh[i];
      shared_data.inc_n();
    }
    incoming--;
  }

  // still need to wait for the send requests
  std::vector<MPI_Status> mult_status(procs.size());
  int success = MPI_Waitall(procs.size(), &send_reqs[0], &mult_status[0]);
  if (MPI_SUCCESS != success) {
    MB_SET_ERR(MB_FAILURE, "Failed in waitall in ScdInterface::tag_shared_vertices");
  }
    // sort by local handle
  TupleList::buffer sort_buffer;
  sort_buffer.buffer_init(shared_indices.size()/2);
  shared_data.sort(1, &sort_buffer);
  sort_buffer.reset();
  
    // process into sharing data
  std::map<std::vector<int>, std::vector<EntityHandle> > proc_nvecs;
  Range dum;
  rval = pcomm->tag_shared_verts(shared_data, proc_nvecs, dum, 0);
  if (MB_SUCCESS != rval) return rval;
  
    // create interface sets
  rval = pcomm->create_interface_sets(proc_nvecs);
  if (MB_SUCCESS != rval) return rval;

    // add the box to the PComm's partitionSets
  pcomm->partition_sets().insert(box->box_set());

    // make sure buffers are allocated for communicating procs
  for (std::vector<int>::iterator pit = procs.begin(); pit != procs.end(); ++pit)
    pcomm->get_buffers(*pit);

  if (pcomm->get_debug_verbosity() > 1) pcomm->list_entities(NULL, 1);

#ifndef NDEBUG
  rval = pcomm->check_all_shared_handles();
  if (MB_SUCCESS != rval) return rval;
#endif
  
  return MB_SUCCESS;
  
#endif
}
Beispiel #13
0
// Generic load function for both ASCII and binary. Calls
// pure-virtual function implemented in subclasses to read
// the data from the file.
ErrorCode ReadSTL::load_file(const char* filename,
                             const EntityHandle* /* file_set */,
                             const FileOptions& opts,
                             const ReaderIface::SubsetList* subset_list,
                             const Tag* file_id_tag)
{
  if (subset_list) {
    MB_SET_ERR(MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for STL");
  }

  ErrorCode result;

  std::vector<ReadSTL::Triangle> triangles;

  bool is_ascii = false, is_binary = false;
  if (MB_SUCCESS == opts.get_null_option("ASCII"))
    is_ascii = true;
  if (MB_SUCCESS == opts.get_null_option("BINARY"))
    is_binary = true;
  if (is_ascii && is_binary) {
    MB_SET_ERR(MB_FAILURE, "Conflicting options: BINARY ASCII");
  }

  bool big_endian = false, little_endian = false;
  if (MB_SUCCESS == opts.get_null_option("BIG_ENDIAN"))
    big_endian = true;
  if (MB_SUCCESS == opts.get_null_option("LITTLE_ENDIAN"))
    little_endian = true;
  if (big_endian && little_endian) {
    MB_SET_ERR(MB_FAILURE, "Conflicting options: BIG_ENDIAN LITTLE_ENDIAN");
  }
  ByteOrder byte_order =    big_endian ? STL_BIG_ENDIAN
                       : little_endian ? STL_LITTLE_ENDIAN
                       :                 STL_UNKNOWN_BYTE_ORDER;

  if (is_ascii)
    result = ascii_read_triangles(filename, triangles);
  else if (is_binary)
    result = binary_read_triangles(filename, byte_order, triangles);
  else {
    // Try ASCII first
    result = ascii_read_triangles(filename, triangles);
    if (MB_SUCCESS != result) 
      // ASCII failed, try binary
      result = binary_read_triangles(filename, byte_order, triangles);
  }
  if (MB_SUCCESS != result)
    return result;

  // Create a std::map from position->handle, and such
  // that all positions are specified, and handles are zero.
  std::map<Point, EntityHandle> vertex_map;
  for (std::vector<Triangle>::iterator i = triangles.begin(); i != triangles.end(); ++i) {
    vertex_map[i->points[0]] = 0;
    vertex_map[i->points[1]] = 0;
    vertex_map[i->points[2]] = 0;
  }

  // Create vertices
  std::vector<double*> coord_arrays;
  EntityHandle vtx_handle = 0;
  result = readMeshIface->get_node_coords(3, vertex_map.size(), MB_START_ID,
                                          vtx_handle, coord_arrays);
  if (MB_SUCCESS != result)
    return result;

  // Copy vertex coordinates into entity sequence coordinate arrays
  // and copy handle into vertex_map.
  double *x = coord_arrays[0], *y = coord_arrays[1], *z = coord_arrays[2];
  for (std::map<Point, EntityHandle>::iterator i = vertex_map.begin();
       i != vertex_map.end(); ++i) {
    i->second = vtx_handle; ++vtx_handle;
    *x = i->first.coords[0]; ++x;
    *y = i->first.coords[1]; ++y;
    *z = i->first.coords[2]; ++z;
  }

  // Allocate triangles
  EntityHandle elm_handle = 0;
  EntityHandle* connectivity;
  result = readMeshIface->get_element_connect(triangles.size(),
                                              3,
                                              MBTRI,
                                              MB_START_ID,
                                              elm_handle,
                                              connectivity);
  if (MB_SUCCESS != result)
    return result;

  // Use vertex_map to recover triangle connectivity from
  // vertex coordinates.
  EntityHandle *conn_sav = connectivity;
  for (std::vector<Triangle>::iterator i = triangles.begin(); i != triangles.end(); ++i) {
    *connectivity = vertex_map[i->points[0]]; ++connectivity;
    *connectivity = vertex_map[i->points[1]]; ++connectivity;
    *connectivity = vertex_map[i->points[2]]; ++connectivity;
  }

  // Notify MOAB of the new elements
  result = readMeshIface->update_adjacencies(elm_handle, triangles.size(),
                                             3, conn_sav);
  if (MB_SUCCESS != result)
    return result;

  if (file_id_tag) {
    Range vertices(vtx_handle, vtx_handle + vertex_map.size() - 1);
    Range elements(elm_handle, elm_handle + triangles.size() - 1);
    readMeshIface->assign_ids(*file_id_tag, vertices);
    readMeshIface->assign_ids(*file_id_tag, elements);
  }

  return MB_SUCCESS;
}
Beispiel #14
0
//! Writes out a file
ErrorCode WriteGmsh::write_file(const char *file_name,
                                const bool overwrite,
                                const FileOptions& options,
                                const EntityHandle *output_list,
                                const int num_sets,
                                const std::vector<std::string>& /* qa_list */,
                                const Tag* /* tag_list */,
                                int /* num_tags */,
                                int /* export_dimension */)
{
  ErrorCode rval;
  Tag global_id = 0, block_tag = 0, geom_tag = 0, prtn_tag = 0;

  if (!overwrite) {
    rval = mWriteIface->check_doesnt_exist(file_name);
    if (MB_SUCCESS != rval)
      return rval;
  }

  // Get tags
  mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, global_id);
  mbImpl->tag_get_handle(MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, block_tag);
  if (global_id) 
    mbImpl->tag_get_handle(GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag);
  mbImpl->tag_get_handle(PARALLEL_PARTITION_TAG_NAME, 1, MB_TYPE_INTEGER, prtn_tag);

  // Define arrays to hold entity sets of interest
  Range sets[3];
  Tag set_tags[] = {block_tag, geom_tag, prtn_tag};
  Tag set_ids[] = {block_tag, 0 /*global_id*/, prtn_tag};

  // Get entities to write
  Range elements, nodes;
  if (!output_list) {
    rval = mbImpl->get_entities_by_dimension(0, 0, nodes, false);
    if (MB_SUCCESS != rval)
      return rval;
    for (int d = 1; d < 3; ++d) {
      Range tmp_range;
      rval = mbImpl->get_entities_by_dimension(0, d, tmp_range, false);
      if (MB_SUCCESS != rval)
        return rval;
      elements.merge(tmp_range);
    }

    for (int s = 0; s < 3; ++s) {
      if (set_tags[s]) {
        rval = mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, set_tags + s, 0, 1, sets[s]);
        if (MB_SUCCESS != rval)
          return rval;
      }
    }
  }
  else {
    for (int i = 0; i < num_sets; ++i) {
      EntityHandle set = output_list[i];
      for (int d = 1; d < 3; ++d) {
        Range tmp_range, tmp_nodes;
        rval = mbImpl->get_entities_by_dimension(set, d, tmp_range, true);
        if (rval != MB_SUCCESS)
          return rval;
        elements.merge(tmp_range);
        rval = mbImpl->get_adjacencies(tmp_range, set, false, tmp_nodes);
        if (rval != MB_SUCCESS)
          return rval;
        nodes.merge(tmp_nodes);
      }

      for (int s = 0; s < 3; ++s) {
        if (set_tags[s]) {
          Range tmp_range;
          rval = mbImpl->get_entities_by_type_and_tag(set, MBENTITYSET, set_tags + s, 0, 1, tmp_range);
          if (MB_SUCCESS != rval)
            return rval;
          sets[s].merge(tmp_range);
          int junk;
          rval = mbImpl->tag_get_data(set_tags[s], &set, 1, &junk);
          if (MB_SUCCESS == rval)
            sets[s].insert(set);
        }
      }
    }
  }

  if (elements.empty()) {
    MB_SET_ERR(MB_ENTITY_NOT_FOUND, "Nothing to write");
  }

  // Get global IDs for all elements.
  // First try to get from tag.  If tag is not defined or not set
  // for all elements, use handle value instead.
  std::vector<int> global_id_array(elements.size());
  std::vector<int>::iterator id_iter;
  if (!global_id || MB_SUCCESS !=
      mbImpl->tag_get_data(global_id, elements, &global_id_array[0])) {
    id_iter = global_id_array.begin();
    for (Range::iterator i = elements.begin(); i != elements.end(); ++i, ++id_iter)
      *id_iter = mbImpl->id_from_handle(*i);
  }

  // Figure out the maximum ID value so we know where to start allocating
  // new IDs when we encounter ID conflicts.
  int max_id = 0;
  for (id_iter = global_id_array.begin(); id_iter != global_id_array.end(); ++id_iter)
    if (*id_iter > max_id)
      max_id = *id_iter;

  // Initialize ElemInfo struct for each element
  std::map<EntityHandle, ElemInfo> elem_sets; // Per-element info
  std::set<int> elem_global_ids; // Temporary for finding duplicate IDs
  id_iter = global_id_array.begin();
  // Iterate backwards to give highest-dimension entities first dibs for
  // a conflicting ID.
  for (Range::reverse_iterator i = elements.rbegin(); i != elements.rend(); ++i) {
    int id = *id_iter;
    ++id_iter;
    if (!elem_global_ids.insert(id).second)
      id = max_id++;

    ElemInfo& ei = elem_sets[*i];
    ei.count = 0;
    ei.id = id;

    EntityType type = mbImpl->type_from_handle(*i);
    int num_vtx;
    const EntityHandle* conn;
    rval = mbImpl->get_connectivity(*i, conn, num_vtx);
    if (MB_SUCCESS != rval)
      return rval;

    ei.type = GmshUtil::get_gmsh_type(type, num_vtx);
    if (ei.type < 0) {
      MB_SET_ERR(MB_FILE_WRITE_ERROR, "Gmem file format does not support element of type " << CN::EntityTypeName(type) << " with " << num_vtx << " vertices");
    }
  }
  // Don't need these any more, free memory.
  elem_global_ids.clear();
  global_id_array.clear();

  // For each material set, geometry set, or partition; store
  // the ID of the set on each element.
  for (int s = 0; s < 3; ++s) {
    if (!set_tags[s])
      continue;

    for (Range::iterator i = sets[s].begin(); i != sets[s].end(); ++i) {
      int id;
      if (set_ids[s]) {
        rval = mbImpl->tag_get_data(set_ids[s], &*i, 1, &id);
        if (MB_SUCCESS != rval)
          return rval;
      }
      else
        id = mbImpl->id_from_handle(*i);

      Range elems;
      rval = mbImpl->get_entities_by_handle(*i, elems);
      if (MB_SUCCESS != rval)
        return rval;

      elems = intersect(elems, elements);
      for (Range::iterator j = elems.begin(); j != elems.end(); ++j)
        elem_sets[*j].set(s, id);
    }
  }

  // Create file
  std::ofstream out(file_name);
  if (!out)
    return MB_FILE_DOES_NOT_EXIST;

  // Write header
  out << "$MeshFormat" << std::endl;
  out << "2.0 0 " << sizeof(double) << std::endl;
  out << "$EndMeshFormat" << std::endl;

  // Set precision for node coordinates
  int precision;
  if (MB_SUCCESS != options.get_int_option("PRECISION", precision))
    precision = DEFAULT_PRECISION;
  const int old_precision = out.precision();
  out.precision(precision);

  // Write nodes
  out << "$Nodes" << std::endl;
  out << nodes.size() << std::endl;
  std::vector<double> coords(3*nodes.size());
  rval = mbImpl->get_coords(nodes, &coords[0]);
  if (MB_SUCCESS != rval)
    return rval;
  std::vector<double>::iterator c = coords.begin();
  for (Range::iterator i = nodes.begin(); i != nodes.end(); ++i) {
    out << mbImpl->id_from_handle(*i);
    out << " " << *c; ++c;
    out << " " << *c; ++c;
    out << " " << *c; ++c;
    out << std::endl;
  }
  out << "$EndNodes" << std::endl;
  coords.clear();

  // Restore stream state
  out.precision(old_precision);

  // Write elements
  out << "$Elements" << std::endl;
  out << elem_sets.size() << std::endl;
  for (std::map<EntityHandle, ElemInfo>::iterator i = elem_sets.begin();
       i != elem_sets.end(); ++i) {
    int num_vtx;
    const EntityHandle* conn;
    rval = mbImpl->get_connectivity(i->first, conn, num_vtx);
    if (MB_SUCCESS != rval)
      return rval;
    out << i->second.id << ' ' << i->second.type << ' ' << i->second.count;
    for (int j = 0; j < i->second.count; ++j)
      out << ' ' << i->second.sets[j];

    const int* order = GmshUtil::gmshElemTypes[i->second.type].node_order;

    // Need to re-order vertices
    if (order) {
      for (int j = 0; j < num_vtx; ++j)
        out << ' ' << mbImpl->id_from_handle(conn[order[j]]);
    }
    else {
      for (int j = 0; j < num_vtx; ++j)
        out << ' ' << mbImpl->id_from_handle(conn[j]);
    }
    out << std::endl;
  }
  out << "$EndElements" << std::endl;

  // Done
  return MB_SUCCESS;
}
Beispiel #15
0
ErrorCode ReadNC::get_variables()
{
  // First cache the number of time steps
  std::vector<std::string>::iterator vit = std::find(dimNames.begin(), dimNames.end(), "time");
  if (vit == dimNames.end())
    vit = std::find(dimNames.begin(), dimNames.end(), "t");

  int ntimes = 0;
  if (vit != dimNames.end())
    ntimes = dimLens[vit - dimNames.begin()];
  if (!ntimes)
    ntimes = 1;

  // Get the number of variables
  int num_vars;
  int success = NCFUNC(inq_nvars)(fileId, &num_vars);
  if (success)
    MB_SET_ERR(MB_FAILURE, "Trouble getting number of variables");

  if (num_vars > NC_MAX_VARS) {
    MB_SET_ERR(MB_FAILURE, "ReadNC: File contains " << num_vars << " vars but NetCDF library supports only " << NC_MAX_VARS);
  }

  char var_name[NC_MAX_NAME + 1];
  int var_ndims;

  for (int i = 0; i < num_vars; i++) {
    // Get the name first, so we can allocate a map iterate for this var
    success = NCFUNC(inq_varname )(fileId, i, var_name);
    if (success)
      MB_SET_ERR(MB_FAILURE, "Trouble getting variable name");
    VarData &data = varInfo[std::string(var_name)];
    data.varName = std::string(var_name);
    data.varId = i;
    data.varTags.resize(ntimes, 0);

    // Get the data type
    success = NCFUNC(inq_vartype)(fileId, i, &data.varDataType);
    if (success)
      MB_SET_ERR(MB_FAILURE, "Trouble getting data type for variable " << data.varName);

    // Get the number of dimensions, then the dimensions
    success = NCFUNC(inq_varndims)(fileId, i, &var_ndims);
    if (success)
      MB_SET_ERR(MB_FAILURE, "Trouble getting number of dims for variable " << data.varName);
    data.varDims.resize(var_ndims);

    success = NCFUNC(inq_vardimid)(fileId, i, &data.varDims[0]);
    if (success)
      MB_SET_ERR(MB_FAILURE, "Trouble getting dimensions for variable " << data.varName);

    // Finally, get the number of attributes, then the attributes
    success = NCFUNC(inq_varnatts)(fileId, i, &data.numAtts);
    if (success)
      MB_SET_ERR(MB_FAILURE, "Trouble getting number of dims for variable " << data.varName);

    // Print debug info here so attribute info comes afterwards
    dbgOut.tprintf(2, "Variable %s: Id=%d, numAtts=%d, datatype=%d, num_dims=%u\n", data.varName.c_str(), data.varId, data.numAtts,
        data.varDataType, (unsigned int) data.varDims.size());

    ErrorCode rval = get_attributes(i, data.numAtts, data.varAtts, "   ");MB_CHK_SET_ERR(rval, "Trouble getting attributes for variable " << data.varName);
  }

  return MB_SUCCESS;
}
Beispiel #16
0
ErrorCode ReadNC::load_file(const char* file_name, const EntityHandle* file_set, const FileOptions& opts,
                            const ReaderIface::SubsetList* /*subset_list*/, const Tag* file_id_tag)
{
  // See if opts has variable(s) specified
  std::vector<std::string> var_names;
  std::vector<int> tstep_nums;
  std::vector<double> tstep_vals;

  // Get and cache predefined tag handles
  int dum_val = 0;
  ErrorCode rval = mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, mGlobalIdTag, MB_TAG_DENSE | MB_TAG_CREAT,
                                &dum_val);MB_CHK_SET_ERR(rval, "Trouble getting global ID tag");

  // Store the pointer to the tag; if not null, set when global id tag
  // is set too, with the same data, duplicated
  mpFileIdTag = file_id_tag;

  rval = parse_options(opts, var_names, tstep_nums, tstep_vals);MB_CHK_SET_ERR(rval, "Trouble parsing option string");

  // Open the file
  dbgOut.tprintf(1, "Opening file %s\n", file_name);
  fileName = std::string(file_name);
  int success;

#ifdef MOAB_HAVE_PNETCDF
  if (isParallel)
    success = NCFUNC(open)(myPcomm->proc_config().proc_comm(), file_name, 0, MPI_INFO_NULL, &fileId);
  else
    success = NCFUNC(open)(MPI_COMM_SELF, file_name, 0, MPI_INFO_NULL, &fileId);
#else
  success = NCFUNC(open)(file_name, 0, &fileId);
#endif
  if (success)
    MB_SET_ERR(MB_FAILURE, "Trouble opening file " << file_name);

  // Read the header (num dimensions, dimensions, num variables, global attribs)
  rval = read_header();MB_CHK_SET_ERR(rval, "Trouble reading file header");

  // Make sure there's a file set to put things in
  EntityHandle tmp_set;
  if (noMesh && !file_set) {
    MB_SET_ERR(MB_FAILURE, "NOMESH option requires non-NULL file set on input");
  }
  else if (!file_set || (file_set && *file_set == 0)) {
    rval = mbImpl->create_meshset(MESHSET_SET, tmp_set);MB_CHK_SET_ERR(rval, "Trouble creating file set");
  }
  else
    tmp_set = *file_set;

  // Get the scd interface
  scdi = NULL;
  rval = mbImpl->query_interface(scdi);
  if (NULL == scdi)
    return MB_FAILURE;

  if (NULL != myHelper)
    delete myHelper;

  // Get appropriate NC helper instance based on information read from the header
  myHelper = NCHelper::get_nc_helper(this, fileId, opts, tmp_set);
  if (NULL == myHelper) {
    MB_SET_ERR(MB_FAILURE, "Failed to get NCHelper class instance");
  }

  // Initialize mesh values
  rval = myHelper->init_mesh_vals();MB_CHK_SET_ERR(rval, "Trouble initializing mesh values");

  // Check existing mesh from last read
  if (noMesh && !noVars) {
    rval = myHelper->check_existing_mesh();MB_CHK_SET_ERR(rval, "Trouble checking mesh from last read");
  }

  // Create some conventional tags, e.g. __NUM_DIMS
  // For multiple reads to a specified file set, we assume a single file, or a series of
  // files with separated timesteps. Keep a flag on the file set to prevent conventional
  // tags from being created again on a second read
  Tag convTagsCreated = 0;
  int def_val = 0;
  rval = mbImpl->tag_get_handle("__CONV_TAGS_CREATED", 1, MB_TYPE_INTEGER, convTagsCreated,
                                MB_TAG_SPARSE | MB_TAG_CREAT, &def_val);MB_CHK_SET_ERR(rval, "Trouble getting _CONV_TAGS_CREATED tag");
  int create_conv_tags_flag = 0;
  rval = mbImpl->tag_get_data(convTagsCreated, &tmp_set, 1, &create_conv_tags_flag);
  // The first read to the file set
  if (0 == create_conv_tags_flag) {
    // Read dimensions (coordinate variables) by default to create tags like __<var_name>_DIMS
    // This is done only once (assume that all files read to the file set have the same dimensions)
    rval = myHelper->read_variables(dimNames, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble reading dimensions");

    rval = myHelper->create_conventional_tags(tstep_nums);MB_CHK_SET_ERR(rval, "Trouble creating NC conventional tags");

    create_conv_tags_flag = 1;
    rval = mbImpl->tag_set_data(convTagsCreated, &tmp_set, 1, &create_conv_tags_flag);MB_CHK_SET_ERR(rval, "Trouble setting data to _CONV_TAGS_CREATED tag");
  }
  // Another read to the file set
  else {
    if (tStepBase > -1) {
      // If timesteps spread across files, merge time values read
      // from current file to existing time tag
      rval = myHelper->update_time_tag_vals();MB_CHK_SET_ERR(rval, "Trouble updating time tag values");
    }
  }

  // Create mesh vertex/edge/face sequences
  Range faces;
  if (!noMesh) {
    rval = myHelper->create_mesh(faces);MB_CHK_SET_ERR(rval, "Trouble creating mesh");
  }

  // Read specified variables onto grid
  if (!noVars) {
    if (var_names.empty()) {
      // If VARIABLE option is missing, read all variables
      rval = myHelper->read_variables(var_names, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble reading all variables");
    }
    else {
      // Exclude dimensions that are read to the file set by default
      std::vector<std::string> non_dim_var_names;
      for (unsigned int i = 0; i < var_names.size(); i++) {
        if (std::find(dimNames.begin(), dimNames.end(), var_names[i]) == dimNames.end())
          non_dim_var_names.push_back(var_names[i]);
      }

      if (!non_dim_var_names.empty()) {
        rval = myHelper->read_variables(non_dim_var_names, tstep_nums);MB_CHK_SET_ERR(rval, "Trouble reading specified variables");
      }
    }
  }

#ifdef MOAB_HAVE_MPI
  // Create partition set, and populate with elements
  if (isParallel) {
    EntityHandle partn_set;
    rval = mbImpl->create_meshset(MESHSET_SET, partn_set);MB_CHK_SET_ERR(rval, "Trouble creating partition set");

    rval = mbImpl->add_entities(partn_set, faces);MB_CHK_SET_ERR(rval, "Couldn't add new faces to partition set");

    Range verts;
    rval = mbImpl->get_connectivity(faces, verts);MB_CHK_SET_ERR(rval, "Couldn't get verts of faces");

    rval = mbImpl->add_entities(partn_set, verts);MB_CHK_SET_ERR(rval, "Couldn't add new verts to partition set");

    myPcomm->partition_sets().insert(partn_set);

    // Write partition tag name on partition set
    Tag part_tag = myPcomm->partition_tag();
    int dum_rank = myPcomm->proc_config().proc_rank();
    rval = mbImpl->tag_set_data(part_tag, &partn_set, 1, &dum_rank);MB_CHK_SET_ERR(rval, "Trouble writing partition tag name on partition set");
  }
#endif

  mbImpl->release_interface(scdi);
  scdi = NULL;

  // Close the file
  success = NCFUNC(close)(fileId);
  if (success)
    MB_SET_ERR(MB_FAILURE, "Trouble closing file");

  return MB_SUCCESS;
}
Beispiel #17
0
ErrorCode WriteVtk::gather_mesh(const EntityHandle* set_list,
                                int num_sets,
                                Range& nodes,
                                Range& elems)
{
  ErrorCode rval;
  int e;

  if (!set_list || !num_sets) {
    Range a;
    rval = mbImpl->get_entities_by_handle(0, a);
    if (MB_SUCCESS != rval)
      return rval;

    Range::const_iterator node_i, elem_i, set_i;
    node_i = a.lower_bound(a.begin(), a.end(), CREATE_HANDLE(   MBVERTEX, 0, e));
    elem_i = a.lower_bound(   node_i, a.end(), CREATE_HANDLE(     MBEDGE, 0, e));
    set_i  = a.lower_bound(   elem_i, a.end(), CREATE_HANDLE(MBENTITYSET, 0, e));
    nodes.merge(node_i, elem_i);
    elems.merge(elem_i, set_i);

    // Filter out unsupported element types
    EntityType et = MBEDGE;
    for (et++; et < MBENTITYSET; et++) {
      if (VtkUtil::get_vtk_type(et, CN::VerticesPerEntity(et)))
        continue;
      Range::iterator
        eit = elems.lower_bound(elems.begin(), elems.end(), CREATE_HANDLE(et, 0, e)),
        ep1it = elems.lower_bound(elems.begin(), elems.end(), CREATE_HANDLE(et + 1, 0, e));
      elems.erase(eit, ep1it);
    }
  }
  else {
    std::set<EntityHandle> visited;
    std::vector<EntityHandle> sets;
    sets.reserve(num_sets);
    std::copy(set_list, set_list + num_sets, std::back_inserter(sets));
    while (!sets.empty()) {
      // Get next set
      EntityHandle set = sets.back();
      sets.pop_back();
      // Skip sets we've already done
      if (!visited.insert(set).second)
        continue;

      Range a;
      rval = mbImpl->get_entities_by_handle(set, a);
      if (MB_SUCCESS != rval)
        return rval;

      Range::const_iterator node_i, elem_i, set_i;
      node_i = a.lower_bound(a.begin(), a.end(), CREATE_HANDLE(   MBVERTEX, 0, e));
      elem_i = a.lower_bound(   node_i, a.end(), CREATE_HANDLE(     MBEDGE, 0, e));
      set_i  = a.lower_bound(   elem_i, a.end(), CREATE_HANDLE(MBENTITYSET, 0, e));
      nodes.merge(node_i, elem_i);
      elems.merge(elem_i, set_i);
      std::copy(set_i, a.end(), std::back_inserter(sets));

      a.clear();
      rval = mbImpl->get_child_meshsets(set, a);
      std::copy(a.begin(), a.end(), std::back_inserter(sets));
    }

    for (Range::const_iterator ei = elems.begin(); ei != elems.end(); ++ei) {
      std::vector<EntityHandle> connect;
      rval = mbImpl->get_connectivity(&(*ei), 1, connect);
      if (MB_SUCCESS != rval)
        return rval;

      for (unsigned int i = 0; i < connect.size(); ++i)
        nodes.insert(connect[i]);
    }
  }

  if (nodes.empty()) {
    MB_SET_ERR(MB_ENTITY_NOT_FOUND, "Nothing to write");
  }

  return MB_SUCCESS;
}
Beispiel #18
0
ErrorCode ReadNC::parse_options(const FileOptions& opts, std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
                                std::vector<double>& tstep_vals)
{
  int tmpval;
  if (MB_SUCCESS == opts.get_int_option("DEBUG_IO", 1, tmpval)) {
    dbgOut.set_verbosity(tmpval);
    dbgOut.set_prefix("NC ");
  }

  ErrorCode rval = opts.get_strs_option("VARIABLE", var_names);
  if (MB_TYPE_OUT_OF_RANGE == rval)
    noVars = true;
  else
    noVars = false;

  opts.get_ints_option("TIMESTEP", tstep_nums);
  opts.get_reals_option("TIMEVAL", tstep_vals);

  rval = opts.get_null_option("NOMESH");
  if (MB_SUCCESS == rval)
    noMesh = true;

  rval = opts.get_null_option("SPECTRAL_MESH");
  if (MB_SUCCESS == rval)
    spectralMesh = true;

  rval = opts.get_null_option("NO_MIXED_ELEMENTS");
  if (MB_SUCCESS == rval)
    noMixedElements = true;

  rval = opts.get_null_option("NO_EDGES");
  if (MB_SUCCESS == rval)
    noEdges = true;

  if (2 <= dbgOut.get_verbosity()) {
    if (!var_names.empty()) {
      std::cerr << "Variables requested: ";
      for (unsigned int i = 0; i < var_names.size(); i++)
        std::cerr << var_names[i];
      std::cerr << std::endl;
    }

    if (!tstep_nums.empty()) {
      std::cerr << "Timesteps requested: ";
      for (unsigned int i = 0; i < tstep_nums.size(); i++)
        std::cerr << tstep_nums[i];
      std::cerr << std::endl;
    }

    if (!tstep_vals.empty()) {
      std::cerr << "Time vals requested: ";
      for (unsigned int i = 0; i < tstep_vals.size(); i++)
        std::cerr << tstep_vals[i];
      std::cerr << std::endl;
    }
  }

  rval = opts.get_int_option("GATHER_SET", 0, gatherSetRank);
  if (MB_TYPE_OUT_OF_RANGE == rval) {
    MB_SET_ERR(rval, "Invalid value for GATHER_SET option");
  }

  rval = opts.get_int_option("TIMESTEPBASE", 0, tStepBase);
  if (MB_TYPE_OUT_OF_RANGE == rval) {
    MB_SET_ERR(rval, "Invalid value for TIMESTEPBASE option");
  }

  rval = opts.get_int_option("TRIVIAL_PARTITION_SHIFT", 1, trivialPartitionShift);
  if (MB_TYPE_OUT_OF_RANGE == rval) {
    MB_SET_ERR(rval, "Invalid value for TRIVIAL_PARTITION_SHIFT option");
  }

#ifdef MOAB_HAVE_MPI
  isParallel = (opts.match_option("PARALLEL", "READ_PART") != MB_ENTITY_NOT_FOUND);

  if (!isParallel)
  // Return success here, since rval still has _NOT_FOUND from not finding option
  // in this case, myPcomm will be NULL, so it can never be used; always check for isParallel 
  // before any use for myPcomm
    return MB_SUCCESS;

  int pcomm_no = 0;
  rval = opts.get_int_option("PARALLEL_COMM", pcomm_no);
  if (MB_TYPE_OUT_OF_RANGE == rval) {
    MB_SET_ERR(rval, "Invalid value for PARALLEL_COMM option");
  }
  myPcomm = ParallelComm::get_pcomm(mbImpl, pcomm_no);
  if (0 == myPcomm) {
    myPcomm = new ParallelComm(mbImpl, MPI_COMM_WORLD);
  }
  const int rank = myPcomm->proc_config().proc_rank();
  dbgOut.set_rank(rank);

  int dum;
  rval = opts.match_option("PARTITION_METHOD", ScdParData::PartitionMethodNames, dum);
  if (MB_FAILURE == rval) {
    MB_SET_ERR(rval, "Unknown partition method specified");
  }
  else if (MB_ENTITY_NOT_FOUND == rval)
    partMethod = ScdParData::ALLJORKORI;
  else
    partMethod = dum;
#endif

  return MB_SUCCESS;
}
Beispiel #19
0
// Read a binary STL file
ErrorCode ReadSTL::binary_read_triangles(const char* name,
                                         ReadSTL::ByteOrder byte_order,
                                         std::vector<ReadSTL::Triangle>& tris)
{
  FILE* file = fopen(name, "rb");
  if (!file) {
    MB_SET_ERR(MB_FILE_DOES_NOT_EXIST, name << ": " << strerror(errno));
  }

  // Read header block
  BinaryHeader header;
  if (fread(&header, 84, 1, file) != 1) {
    fclose(file);
    MB_SET_ERR(MB_FILE_WRITE_ERROR, name << ": " << strerror(errno));
  }

  // Allow user setting for byte order, default to little endian
  const bool want_big_endian = (byte_order == STL_BIG_ENDIAN);
  const bool am_big_endian = !SysUtil::little_endian();
  bool swap_bytes = (want_big_endian == am_big_endian);

  // Compare the number of triangles to the length of the file.
  // The file must contain an 80-byte description, a 4-byte
  // triangle count and 50 bytes per triangle.
  //
  // The triangle count *may* allow us to determine the byte order
  // of the file, if it is not an endian-symmetric value.
  //
  // We need to compare the expected size calculated from the triangle
  // count with the file size anyway, as an invalid file or a byte-
  // swapping issue could result in a very large (incorrect) value for
  // num_tri, resulting in a SEGFAULT.

  // Get expected number of triangles
  if (swap_bytes)
    SysUtil::byteswap(&header.count, 1);
  unsigned long num_tri = header.count;

  // Get the file length
  long filesize = SysUtil::filesize(file);
  if (filesize >= 0) { // -1 indicates could not determine file size (e.g. reading from FIFO)
      // Check file size, but be careful of numeric overflow
    if (ULONG_MAX / 50 - 84 < num_tri || // Next calc would have overflow
        84 + 50 * num_tri != (unsigned long)filesize) {
      // Unless the byte order was specified explicitly in the
      // tag, try the opposite byte order.
      uint32_t num_tri_tmp = header.count;
      SysUtil::byteswap(&num_tri_tmp, 1);
      unsigned long num_tri_swap = num_tri_tmp;
      if (byte_order != STL_UNKNOWN_BYTE_ORDER || // If byte order was specified, fail now
          ULONG_MAX / 50 - 84 < num_tri_swap || // Watch for overflow in next line
          84 + 50 * num_tri_swap != (unsigned long)filesize) {
        fclose(file);
        MB_SET_ERR(MB_FILE_DOES_NOT_EXIST, name << ": not a binary STL file");
      }
      swap_bytes = !swap_bytes;
      num_tri = num_tri_swap;
    }
  }

  // Allocate storage for triangles
  tris.resize(num_tri);

  // Read each triangle
  BinaryTri tri; // Binary block read from file
  for (std::vector<Triangle>::iterator i = tris.begin(); i != tris.end(); ++i) {
    if (fread(&tri, 50, 1, file) != 1) {
      fclose(file);
      MB_SET_ERR(MB_FILE_WRITE_ERROR, name << ": " << strerror(errno));
    }

    if (swap_bytes)
      SysUtil::byteswap(tri.coords, 9);

    for (unsigned j = 0; j < 9; ++j)
      i->points[j / 3].coords[j % 3] = tri.coords[j];
  }

  fclose(file);
  return MB_SUCCESS;
}
Beispiel #20
0
ErrorCode WriteVtk::write_elems(std::ostream& stream,
                                const Range& nodes,
                                const Range& elems)
{
  ErrorCode rval;

  Range connected_nodes;
  rval = mbImpl->get_connectivity(elems, connected_nodes);
  if (MB_SUCCESS != rval)
    return rval;
  Range free_nodes = subtract(nodes, connected_nodes);

  // Get and write counts
  unsigned long num_elems, num_uses;
  num_elems = num_uses = elems.size();
  for (Range::const_iterator i = elems.begin(); i != elems.end(); ++i) {
    EntityType type = mbImpl->type_from_handle(*i);
    if (!VtkUtil::get_vtk_type(type, CN::VerticesPerEntity(type)))
      continue;

    std::vector<EntityHandle> connect;
    rval = mbImpl->get_connectivity(&(*i), 1, connect);

    if (MB_SUCCESS != rval)
      return rval;

    num_uses += connect.size();
  }
  stream << "CELLS " << num_elems + free_nodes.size()<< ' ' << num_uses + 2*free_nodes.size() << std::endl;

  // Write element connectivity
  std::vector<int> conn_data;
  std::vector<unsigned> vtk_types(elems.size() + free_nodes.size() );
  std::vector<unsigned>::iterator t = vtk_types.begin();
  for (Range::const_iterator i = elems.begin(); i != elems.end(); ++i) {
    // Get type information for element
    EntityType type = TYPE_FROM_HANDLE(*i);

    // Get element connectivity
    std::vector<EntityHandle> connect;
    rval = mbImpl->get_connectivity(&(*i), 1, connect);
    int conn_len = connect.size();

    if (MB_SUCCESS != rval)
      return rval;

    // Get VTK type
    const VtkElemType* vtk_type = VtkUtil::get_vtk_type(type, conn_len);
    if (!vtk_type) {
      // Try connectivity with 1 fewer node
      vtk_type = VtkUtil::get_vtk_type(type, conn_len - 1);
      if (vtk_type)
        conn_len--;
      else {
        MB_SET_ERR(MB_FAILURE, "Vtk file format does not support elements of type " << CN::EntityTypeName(type) << " (" << (int)type << ") with " << conn_len << " nodes");
      }
    }

    // Get IDs from vertex handles
    assert(conn_len > 0);
    conn_data.resize(conn_len);
    for (int j = 0; j < conn_len; ++j)
      conn_data[j] = nodes.index(connect[j]);

    // Save VTK type index for later
    *t = vtk_type->vtk_type;
    ++t;

    // Write connectivity list
    stream << conn_len;
    if (vtk_type->node_order)
      for (int k = 0; k < conn_len; ++k)
        stream << ' ' << conn_data[vtk_type->node_order[k]];
    else
      for (int k = 0; k < conn_len; ++k)
        stream << ' ' << conn_data[k];
    stream << std::endl;
  }
  for (Range::const_iterator v=free_nodes.begin(); v!= free_nodes.end(); ++v, ++t)
  {
    EntityHandle node=*v;
    stream << "1 " << nodes.index(node) << std::endl;
    *t = 1;
  }

  // Write element types
  stream << "CELL_TYPES " << vtk_types.size() << std::endl;
  for (std::vector<unsigned>::const_iterator i = vtk_types.begin(); i != vtk_types.end(); ++i)
    stream << *i << std::endl;

  return MB_SUCCESS;
}
Beispiel #21
0
static ErrorCode not_root_set(const std::string& name, EntityHandle h)
{
  MB_SET_ERR(MB_VARIABLE_DATA_LENGTH, "Cannot get/set mesh/global tag " << name << " on non-root-set " << CN::EntityTypeName(TYPE_FROM_HANDLE(h)) << " " << (unsigned long)ID_FROM_HANDLE(h));
}
Beispiel #22
0
ErrorCode ReadCGNS::load_file(const char* filename,
                              const EntityHandle * /*file_set*/,
                              const FileOptions& opts,
                              const ReaderIface::SubsetList* subset_list,
                              const Tag* file_id_tag)
{
  int num_material_sets = 0;
  const int* material_set_list = 0;

  if (subset_list) {
    if (subset_list->tag_list_length > 1 &&
        !strcmp(subset_list->tag_list[0].tag_name, MATERIAL_SET_TAG_NAME)) {
      MB_SET_ERR(MB_UNSUPPORTED_OPERATION, "CGNS supports subset read only by material ID");
    }
    material_set_list = subset_list->tag_list[0].tag_values;
    num_material_sets = subset_list->tag_list[0].num_tag_values;
  }

  ErrorCode result;

  geomSets.clear();
  result = mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER,
                                  globalId, MB_TAG_DENSE | MB_TAG_CREAT, 0);
  if (MB_SUCCESS != result)
    return result;

  // Create set for more convienient check for material set ids
  std::set<int> blocks;
  for (const int* mat_set_end = material_set_list + num_material_sets;
       material_set_list != mat_set_end; ++material_set_list)
    blocks.insert(*material_set_list);

  // Map of ID->handle for nodes
  std::map<long, EntityHandle> node_id_map;

  // Save filename to member variable so we don't need to pass as an argument
  // to called functions
  fileName = filename;

  // Process options; see src/FileOptions.hpp for API for FileOptions class, and doc/metadata_info.doc for
  // a description of various options used by some of the readers in MOAB
  result = process_options(opts);MB_CHK_SET_ERR(result, fileName << ": problem reading options");

  // Open file
  int filePtr = 0;

  cg_open(filename, CG_MODE_READ, &filePtr);

  if (filePtr <= 0) {
    MB_SET_ERR(MB_FILE_DOES_NOT_EXIST, fileName << ": fopen returned error");
  }

  // Read number of verts, elements, sets
  long num_verts = 0, num_elems = 0, num_sets = 0;
  int num_bases = 0, num_zones = 0, num_sections = 0;

  char zoneName[128];
  cgsize_t size[3];

  mesh_dim = 3; // Default to 3D

  // Read number of bases;
  cg_nbases(filePtr, &num_bases);

  if (num_bases > 1) {
    MB_SET_ERR(MB_NOT_IMPLEMENTED, fileName << ": support for number of bases > 1 not implemented");
  }

  for (int indexBase = 1; indexBase <= num_bases; ++indexBase) {
    // Get the number of zones/blocks in current base.
    cg_nzones(filePtr, indexBase, &num_zones);

    if (num_zones > 1) {
      MB_SET_ERR(MB_NOT_IMPLEMENTED, fileName << ": support for number of zones > 1 not implemented");
    }

    for (int indexZone = 1; indexZone <= num_zones; ++indexZone) {
      // Get zone name and size.
      cg_zone_read(filePtr, indexBase, indexZone, zoneName, size);

      // Read number of sections/Parts in current zone.
      cg_nsections(filePtr, indexBase, indexZone, &num_sections);

      num_verts = size[0];
      num_elems = size[1];
      num_sets = num_sections;

      std::cout << "\nnumber of nodes = " << num_verts;
      std::cout << "\nnumber of elems = " << num_elems;
      std::cout << "\nnumber of parts = " << num_sets << std::endl;

      // //////////////////////////////////
      // Read Nodes

      // Allocate nodes; these are allocated in one shot, get contiguous handles starting with start_handle,
      // and the reader is passed back double*'s pointing to MOAB's native storage for vertex coordinates
      // for those verts
      std::vector<double*> coord_arrays;
      EntityHandle handle = 0;
      result = readMeshIface->get_node_coords(3, num_verts, MB_START_ID, handle,
                                              coord_arrays);MB_CHK_SET_ERR(result, fileName << ": Trouble reading vertices");

      // Fill in vertex coordinate arrays
      cgsize_t beginPos = 1, endPos = num_verts;

      // Read nodes coordinates.
      cg_coord_read(filePtr, indexBase, indexZone, "CoordinateX",
                    RealDouble, &beginPos, &endPos, coord_arrays[0]);
      cg_coord_read(filePtr, indexBase, indexZone, "CoordinateY",
                    RealDouble, &beginPos, &endPos, coord_arrays[1]);
      cg_coord_read(filePtr, indexBase, indexZone, "CoordinateZ",
                    RealDouble, &beginPos, &endPos, coord_arrays[2]);

      // CGNS seems to always include the Z component, even if the mesh is 2D.
      // Check if Z is zero and determine mesh dimension.
      // Also create the node_id_map data.
      double sumZcoord = 0.0;
      double eps = 1.0e-12;
      for (long i = 0; i < num_verts; ++i, ++handle) {
        int index = i + 1;

        node_id_map.insert(std::pair<long, EntityHandle>(index, handle)).second;

        sumZcoord += *(coord_arrays[2] + i);
      }
      if (std::abs(sumZcoord) <= eps) mesh_dim = 2;

      // Create reverse map from handle to id
      std::vector<int> ids(num_verts);
      std::vector<int>::iterator id_iter = ids.begin();
      std::vector<EntityHandle> handles(num_verts);
      std::vector<EntityHandle>::iterator h_iter = handles.begin();
      for (std::map<long, EntityHandle>::iterator i = node_id_map.begin();
          i != node_id_map.end(); ++i, ++id_iter, ++h_iter) {
        *id_iter = i->first;
        * h_iter = i->second;
      }
      // Store IDs in tags
      result = mbImpl->tag_set_data(globalId, &handles[0], num_verts, &ids[0]);
      if (MB_SUCCESS != result)
        return result;
      if (file_id_tag) {
        result = mbImpl->tag_set_data(*file_id_tag, &handles[0], num_verts, &ids[0]);
        if (MB_SUCCESS != result)
          return result;
      }
      ids.clear();
      handles.clear();

      // //////////////////////////////////
      // Read elements data

      EntityType ent_type;

      long section_offset = 0;

      // Define which mesh parts are volume families.
      // Mesh parts with volumeID[X] = 0 are boundary parts.
      std::vector<int> volumeID(num_sections, 0);

      for (int section = 0; section < num_sections; ++section) {
        ElementType_t elemsType;
        int iparent_flag, nbndry;
        char sectionName[128];
        int verts_per_elem;

        int cgSection = section + 1;

        cg_section_read(filePtr, indexBase, indexZone, cgSection, sectionName,
                        &elemsType, &beginPos, &endPos, &nbndry, &iparent_flag);

        size_t section_size = endPos - beginPos + 1;

        // Read element description in current section

        switch (elemsType) {
          case BAR_2:
            ent_type = MBEDGE;
            verts_per_elem = 2;
            break;
          case TRI_3:
            ent_type = MBTRI;
            verts_per_elem = 3;
            if (mesh_dim == 2)
              volumeID[section] = 1;
            break;
          case QUAD_4:
            ent_type = MBQUAD;
            verts_per_elem = 4;
            if (mesh_dim == 2)
              volumeID[section] = 1;
            break;
          case TETRA_4:
            ent_type = MBTET;
            verts_per_elem = 4;
            if (mesh_dim == 3)
              volumeID[section] = 1;
              break;
          case PYRA_5:
            ent_type = MBPYRAMID;
            verts_per_elem = 5;
            if (mesh_dim == 3) volumeID[section] = 1;
              break;
          case PENTA_6:
            ent_type = MBPRISM;
            verts_per_elem = 6;
            if (mesh_dim == 3) volumeID[section] = 1;
              break;
          case HEXA_8:
            ent_type = MBHEX;
            verts_per_elem = 8;
            if (mesh_dim == 3) volumeID[section] = 1;
            break;
          case MIXED:
            ent_type = MBMAXTYPE;
            verts_per_elem = 0;
            break;
          default:
            MB_SET_ERR(MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type");
        }

        if (elemsType == TETRA_4 || elemsType == PYRA_5 || elemsType == PENTA_6 || elemsType == HEXA_8 ||
            elemsType == TRI_3   || elemsType == QUAD_4 || ((elemsType == BAR_2) && mesh_dim == 2)) {
          // Read connectivity into conn_array directly

          cgsize_t iparentdata;
          cgsize_t connDataSize;

          // Get number of entries on the connectivity list for this section
          cg_ElementDataSize(filePtr, indexBase, indexZone, cgSection, &connDataSize);

          // Need a temporary vector to later cast to conn_array.
          std::vector<cgsize_t> elemNodes(connDataSize);

          cg_elements_read(filePtr, indexBase, indexZone, cgSection, &elemNodes[0], &iparentdata);

          // //////////////////////////////////
          // Create elements, sets and tags

          create_elements(sectionName, file_id_tag,
                          ent_type, verts_per_elem, section_offset, section_size , elemNodes);
        } // Homogeneous mesh type
        else if (elemsType == MIXED) {
          // We must first sort all elements connectivities into continuous vectors

          cgsize_t connDataSize;
          cgsize_t iparentdata;

          cg_ElementDataSize(filePtr, indexBase, indexZone, cgSection, &connDataSize);

          std::vector< cgsize_t > elemNodes(connDataSize);

          cg_elements_read(filePtr, indexBase, indexZone, cgSection, &elemNodes[0], &iparentdata);

          std::vector<cgsize_t> elemsConn_EDGE;
          std::vector<cgsize_t> elemsConn_TRI, elemsConn_QUAD;
          std::vector<cgsize_t> elemsConn_TET, elemsConn_PYRA, elemsConn_PRISM, elemsConn_HEX;
          cgsize_t count_EDGE, count_TRI, count_QUAD;
          cgsize_t count_TET, count_PYRA, count_PRISM, count_HEX;

          // First, get elements count for current section

          count_EDGE = count_TRI = count_QUAD = 0;
          count_TET = count_PYRA = count_PRISM = count_HEX = 0;

          int connIndex = 0;
          for (int i = beginPos; i <= endPos; i++) {
            elemsType = ElementType_t(elemNodes[connIndex]);

            // Get current cell node count.
            cg_npe(elemsType, &verts_per_elem);

            switch (elemsType) {
              case BAR_2:
                count_EDGE += 1;
                break;
              case TRI_3:
                count_TRI += 1;
                break;
              case QUAD_4:
                count_QUAD += 1;
                break;
              case TETRA_4:
                count_TET += 1;
                break;
              case PYRA_5:
                count_PYRA += 1;
                break;
              case PENTA_6:
                count_PRISM += 1;
                break;
              case HEXA_8:
                count_HEX += 1;
                break;
              default:
                MB_SET_ERR(MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type");
            }

            connIndex += (verts_per_elem + 1); // Add one to skip next element descriptor
          }

          if (count_EDGE  > 0) elemsConn_EDGE.resize(count_EDGE * 2);
          if (count_TRI   > 0) elemsConn_TRI.resize(count_TRI * 3);
          if (count_QUAD  > 0) elemsConn_QUAD.resize(count_QUAD * 4);
          if (count_TET   > 0) elemsConn_TET.resize(count_TET * 4);
          if (count_PYRA  > 0) elemsConn_PYRA.resize(count_PYRA * 5);
          if (count_PRISM > 0) elemsConn_PRISM.resize(count_PRISM * 6);
          if (count_HEX   > 0) elemsConn_HEX.resize(count_HEX * 8);

          // Grab mixed section elements connectivity

          int idx_edge, idx_tri, idx_quad;
          int idx_tet, idx_pyra, idx_prism, idx_hex;
          idx_edge = idx_tri = idx_quad = 0;
          idx_tet = idx_pyra = idx_prism = idx_hex = 0;

          connIndex = 0;
          for (int i = beginPos; i <= endPos; i++) {
            elemsType = ElementType_t(elemNodes[connIndex]);

            // Get current cell node count.
            cg_npe(elemsType, &verts_per_elem);

            switch (elemsType) {
              case BAR_2:
                for (int j = 0; j < 2; ++j)
                  elemsConn_EDGE[idx_edge + j] = elemNodes[connIndex + j + 1];
                idx_edge += 2;
                break;
              case TRI_3:
                for (int j = 0; j < 3; ++j)
                  elemsConn_TRI[idx_tri + j] = elemNodes[connIndex + j + 1];
                idx_tri += 3;
                break;
              case QUAD_4:
                for (int j = 0; j < 4; ++j)
                  elemsConn_QUAD[idx_quad + j] = elemNodes[connIndex + j + 1];
                idx_quad += 4;
                break;
              case TETRA_4:
                for (int j = 0; j < 4; ++j)
                  elemsConn_TET[idx_tet + j] = elemNodes[connIndex + j + 1];
                idx_tet += 4;
                break;
              case PYRA_5:
                for (int j = 0; j < 5; ++j)
                  elemsConn_PYRA[idx_pyra + j] = elemNodes[connIndex + j + 1];
                idx_pyra += 5;
                break;
              case PENTA_6:
                for (int j = 0; j < 6; ++j)
                  elemsConn_PRISM[idx_prism + j] = elemNodes[connIndex + j + 1];
                idx_prism += 6;
                break;
              case HEXA_8:
                for (int j = 0; j < 8; ++j)
                  elemsConn_HEX[idx_hex + j] = elemNodes[connIndex + j + 1];
                idx_hex += 8;
                break;
              default:
                MB_SET_ERR(MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type");
            }

            connIndex += (verts_per_elem + 1); // Add one to skip next element descriptor
          }

          // //////////////////////////////////
          // Create elements, sets and tags

          if (count_EDGE > 0)
            create_elements(sectionName, file_id_tag, MBEDGE, 2, section_offset, count_EDGE, elemsConn_EDGE);

          if (count_TRI > 0)
            create_elements(sectionName, file_id_tag, MBTRI, 3, section_offset, count_TRI, elemsConn_TRI);

          if (count_QUAD > 0)
            create_elements(sectionName, file_id_tag, MBQUAD, 4, section_offset, count_QUAD, elemsConn_QUAD);

          if (count_TET > 0)
            create_elements(sectionName, file_id_tag, MBTET, 4, section_offset, count_TET, elemsConn_TET);

          if (count_PYRA > 0)
            create_elements(sectionName, file_id_tag, MBPYRAMID, 5, section_offset, count_PYRA, elemsConn_PYRA);

          if (count_PRISM > 0)
            create_elements(sectionName, file_id_tag, MBPRISM, 6, section_offset, count_PRISM, elemsConn_PRISM);

          if (count_HEX > 0)
            create_elements(sectionName, file_id_tag, MBHEX, 8, section_offset, count_HEX, elemsConn_HEX);
        } // Mixed mesh type
      } // num_sections

      cg_close(filePtr);

      return result;
    } // indexZone for
  } // indexBase for

  return MB_SUCCESS;
}
Beispiel #23
0
ErrorCode ReadGmsh::load_file(const char* filename,
                              const EntityHandle*,
                              const FileOptions&,
                              const ReaderIface::SubsetList* subset_list,
                              const Tag* file_id_tag)
{
  int num_material_sets = 0;
  const int* material_set_list = 0;
  int zero = 0;
  if (subset_list) {
    if (subset_list->tag_list_length > 1 && 
        !strcmp(subset_list->tag_list[0].tag_name, MATERIAL_SET_TAG_NAME)) {
      MB_SET_ERR(MB_UNSUPPORTED_OPERATION, "GMsh supports subset read only by material ID");
    }
    material_set_list = subset_list->tag_list[0].tag_values;
    num_material_sets = subset_list->tag_list[0].num_tag_values;
  }

  geomSets.clear();
  ErrorCode result = mdbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER,
                                             globalId, MB_TAG_DENSE | MB_TAG_CREAT, &zero);
  if (MB_SUCCESS != result)
    return result;

  // Create set for more convenient check for material set ids
  std::set<int> blocks;
  for (const int* mat_set_end = material_set_list + num_material_sets;
       material_set_list != mat_set_end; ++material_set_list)
    blocks.insert(*material_set_list);
  
  // Map of ID->handle for nodes
  std::map<long, EntityHandle> node_id_map;
  int data_size = 8;

  // Open file and hand off pointer to tokenizer
  FILE* file_ptr = fopen(filename, "r");
  if (!file_ptr) {
    MB_SET_ERR(MB_FILE_DOES_NOT_EXIST, filename << ": " << strerror(errno));
  }
  FileTokenizer tokens(file_ptr, readMeshIface);

  // Determine file format version
  const char* const start_tokens[] = {"$NOD", "$MeshFormat", 0};
  int format_version = tokens.match_token(start_tokens);
  if (!format_version)
    return MB_FILE_DOES_NOT_EXIST;

  // If version 2.0, read additional header info
  if (2 == format_version) {
    double version;
    if (!tokens.get_doubles(1, &version))
      return MB_FILE_WRITE_ERROR;

    if (version != 2.0 && version != 2.1 && version != 2.2) {
      MB_SET_ERR(MB_FILE_DOES_NOT_EXIST, filename << ": unknown format version: " << version);
      return MB_FILE_DOES_NOT_EXIST;
    }

    int file_format;
    if (!tokens.get_integers(1, &file_format) || !tokens.get_integers(1,
        &data_size) || !tokens.match_token("$EndMeshFormat"))
           return MB_FILE_WRITE_ERROR;
           // If physical entities in the gmsh file -> discard this
    const char* const phys_tokens[] = { "$Nodes", "$PhysicalNames", 0 };
    int hasPhys = tokens.match_token(phys_tokens);

    if (hasPhys == 2) {
      long num_phys;
      if (!tokens.get_long_ints(1, &num_phys))
        return MB_FILE_WRITE_ERROR;
      for (long loop_phys = 0; loop_phys < num_phys; loop_phys++) {
        long physDim;
        long physGroupNum;
        //char const * physName;
        if (!tokens.get_long_ints(1, &physDim))
          return MB_FILE_WRITE_ERROR;
        if (!tokens.get_long_ints(1, &physGroupNum))
          return MB_FILE_WRITE_ERROR;
        const char * ptc = tokens.get_string();
        if (!ptc)
          return MB_FILE_WRITE_ERROR;
        // try to get to the end of the line, without reporting errors
        // really, we need to skip this
        while(!tokens.get_newline(false))
          ptc = tokens.get_string();
      }
      if (!tokens.match_token("$EndPhysicalNames") || !tokens.match_token(
          "$Nodes"))
        return MB_FILE_WRITE_ERROR;
    }
  }

  // Read number of nodes
  long num_nodes;
  if (!tokens.get_long_ints(1, &num_nodes))
    return MB_FILE_WRITE_ERROR;

  // Allocate nodes
  std::vector<double*> coord_arrays;
  EntityHandle handle = 0;
  result = readMeshIface->get_node_coords(3, num_nodes, MB_START_ID,
                                          handle, coord_arrays);
  if (MB_SUCCESS != result)
    return result;

  // Read nodes
  double *x = coord_arrays[0],
         *y = coord_arrays[1],
         *z = coord_arrays[2];
  for (long i = 0; i < num_nodes; ++i, ++handle) {
    long id;
    if (!tokens.get_long_ints(1, &id) ||
        !tokens.get_doubles(1, x++) ||
        !tokens.get_doubles(1, y++) ||
        !tokens.get_doubles(1, z++))
      return MB_FILE_WRITE_ERROR;

    if (!node_id_map.insert(std::pair<long, EntityHandle>(id, handle)).second) {
      MB_SET_ERR(MB_FILE_WRITE_ERROR, "Duplicate node ID at line " << tokens.line_number());
    }
  }

  // Create reverse map from handle to id
  std::vector<int> ids(num_nodes);
  std::vector<int>::iterator id_iter = ids.begin();
  std::vector<EntityHandle> handles(num_nodes);
  std::vector<EntityHandle>::iterator h_iter = handles.begin();
  for (std::map<long, EntityHandle>::iterator i = node_id_map.begin();
      i != node_id_map.end(); ++i, ++id_iter, ++h_iter) {
    *id_iter = i->first;
    * h_iter = i->second;
  }
  // Store IDs in tags
  result = mdbImpl->tag_set_data(globalId, &handles[0], num_nodes, &ids[0]);
  if (MB_SUCCESS != result)
    return result;
  if (file_id_tag) {
    result = mdbImpl->tag_set_data(*file_id_tag, &handles[0], num_nodes, &ids[0]);
    if (MB_SUCCESS != result) 
      return result;
  }
  ids.clear();
  handles.clear();

  // Get tokens signifying end of node data and start of elements
  if (!tokens.match_token(format_version == 1 ? "$ENDNOD" : "$EndNodes") ||
      !tokens.match_token(format_version == 1 ? "$ELM" : "$Elements"))
    return MB_FILE_WRITE_ERROR;

  // Get element count
  long num_elem;
  if (!tokens.get_long_ints(1, &num_elem))
    return MB_FILE_WRITE_ERROR;

  // Lists of data accumulated for elements
  std::vector<EntityHandle> connectivity;
  std::vector<int> mat_set_list, geom_set_list, part_set_list, id_list;
  // Temporary, per-element data
  std::vector<int> int_data(5), tag_data(2);
  std::vector<long> tmp_conn;
  int curr_elem_type = -1;
  for (long i = 0; i < num_elem; ++i) {
    // Read element description
    // File format 1.0
    if (1 == format_version) {
      if (!tokens.get_integers(5, &int_data[0]))
        return MB_FILE_WRITE_ERROR;
      tag_data[0] = int_data[2];
      tag_data[1] = int_data[3];
      if ((unsigned)tag_data[1] < GmshUtil::numGmshElemType &&
           GmshUtil::gmshElemTypes[tag_data[1]].num_nodes != (unsigned)int_data[4]) {
        MB_SET_ERR(MB_FILE_WRITE_ERROR, "Invalid node count for element type at line " << tokens.line_number());
      }
    }
    // File format 2.0
    else {
      if (!tokens.get_integers(3, &int_data[0]))
        return MB_FILE_WRITE_ERROR;
      tag_data.resize(int_data[2]);
      if (!tokens.get_integers(tag_data.size(), &tag_data[0]))
        return MB_FILE_WRITE_ERROR;
    }

    // If a list of material sets was specified in the
    // argument list, skip any elements for which the
    // material set is not specified or is not in the
    // passed list.
    if (!blocks.empty() && (tag_data.empty() ||
        blocks.find(tag_data[0]) != blocks.end()))
      continue;

    // If the next element is not the same type as the last one,
    // create a sequence for the block of elements we've read
    // to this point (all of the same type), and clear accumulated
    // data.
    if (int_data[1] != curr_elem_type) {
      if (!id_list.empty()) { // First iteration
        result = create_elements(GmshUtil::gmshElemTypes[curr_elem_type],
                                 id_list,
                                 mat_set_list,
                                 geom_set_list,
                                 part_set_list,
                                 connectivity,
                                 file_id_tag);
        if (MB_SUCCESS != result)
          return result;
      }

      id_list.clear();
      mat_set_list.clear();
      geom_set_list.clear();
      part_set_list.clear();
      connectivity.clear();
      curr_elem_type = int_data[1];
      if ((unsigned)curr_elem_type >= GmshUtil::numGmshElemType ||
          GmshUtil::gmshElemTypes[curr_elem_type].mb_type == MBMAXTYPE) {
        MB_SET_ERR(MB_FILE_WRITE_ERROR, "Unsupported element type " << curr_elem_type << " at line " << tokens.line_number());
      }
      tmp_conn.resize(GmshUtil::gmshElemTypes[curr_elem_type].num_nodes);
    }

    // Store data from element description
    id_list.push_back(int_data[0]);
    part_set_list.push_back(tag_data.size() > 2 ? tag_data[2] : 0);
    geom_set_list.push_back(tag_data.size() > 1 ? tag_data[1] : 0);
     mat_set_list.push_back(tag_data.size() > 0 ? tag_data[0] : 0);

    // Get element connectivity
    if (!tokens.get_long_ints(tmp_conn.size(), &tmp_conn[0]))
      return MB_FILE_WRITE_ERROR;

    // Convert connectivity from IDs to handles
    for (unsigned j = 0; j < tmp_conn.size(); ++j) {
      std::map<long, EntityHandle>::iterator k = node_id_map.find(tmp_conn[j]);
      if (k == node_id_map.end()) {
        MB_SET_ERR(MB_FILE_WRITE_ERROR, "Invalid node ID at line " << tokens.line_number());
      }
      connectivity.push_back(k->second);
    }
  } // for (num_nodes)

  // Create entity sequence for last element(s).
  if (!id_list.empty()) {
    result = create_elements(GmshUtil::gmshElemTypes[curr_elem_type],
                             id_list,
                             mat_set_list,
                             geom_set_list,
                             part_set_list,
                             connectivity,
                             file_id_tag);
    if (MB_SUCCESS != result)
      return result;
  }

  // Construct parent-child relations for geometric sets.
  // Note:  At the time this comment was written, the following
  //        function was not implemented.
  result = create_geometric_topology();
  geomSets.clear();
  return result;
}
Beispiel #24
0
ErrorCode ReadTemplate::load_file(const char* filename,
                                  const EntityHandle *file_set,
                                  const FileOptions& opts,
                                  const ReaderIface::SubsetList* subset_list,
                                  const Tag* /*file_id_tag*/)
{
  if (subset_list) {
    // See src/moab/ReaderIface.hpp, definition of SubsetList struct; this basically specifies
    // an integer tag and tag values for sets to read on this proc, or a part number and total # parts
    // for reading a trivial partition of entities
  }

  // Save filename to member variable so we don't need to pass as an argument
  // to called functions
  fileName = filename;

  // Process options; see src/FileOptions.hpp for API for FileOptions class, and doc/metadata_info.doc for
  // a description of various options used by some of the readers in MOAB
  ErrorCode result = process_options(opts);MB_CHK_SET_ERR(result, fileName << ": problem reading options");

  // Open file; filePtr is member of ReadTemplate, change to whatever mechanism is used to identify file
  FILE* filePtr = fopen(fileName, "r");
  if (!filePtr) {
    MB_SET_ERR(MB_FILE_DOES_NOT_EXIST, fileName << ": fopen returned error");
  }

  // Read number of verts, elements, sets
  long num_verts = 0, num_elems = 0, num_sets = 0;

  // read_ents keeps a running set of entities read from this file, including vertices, elements, and sets;
  // these will get added to file_set (if input) at the end of the read
  Range read_ents;

  // start_vertex is passed back so we know how to convert indices from the file into vertex handles; most
  // of the time this is done by adding start_vertex to the (0-based) index; if the index is 1-based, you also
  // need to subtract one; see read_elements for details
  EntityHandle start_vertex;
  result = read_vertices(num_verts, start_vertex, read_ents);
  if (MB_SUCCESS != result) {
    fclose(filePtr);
    return result;
  }

  // Create/read elements; this template assumes that all elements are the same type, so can be read in a single
  // call to read_elements, and kept track of with a single start_elem handle. If there are more entity types,
  // might have to keep these start handles in an array/vector. start_elem is only really needed if you're reading
  // sets later, and need to convert some file-based index to an entity handle
  EntityHandle start_elem;
  result = read_elements(num_elems, start_vertex, start_elem, read_ents);
  if (MB_SUCCESS != result) {
    fclose(filePtr);
    return result;
  }

  // Read/create entity sets; typically these sets have some tag identifying what they're for, see doc/metadata_info.doc
  // for examples of different kinds of sets and how they're marked
  result = create_sets(num_sets, start_vertex, num_verts, start_elem, num_elems, read_ents);
  if (MB_SUCCESS != result) {
    fclose(filePtr);
    return result;
  }

  // Finally, add all read_ents into the file set, if one was input
  if (file_set && *file_set) {
    result = mbImpl->add_entities(*file_set, read_ents);
    if (MB_SUCCESS != result) {
      fclose(filePtr);
      return result;
    }
  }

  fclose(filePtr);

  return result;
}