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; }
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; }
/** \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); }
// 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; }
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; }
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; }
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()); }
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; }
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; }
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; }
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; }
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 }
// 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; }
//! 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; }
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; }
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; }
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; }
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; }
// 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; }
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; }
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)); }
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; }
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; }
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; }