bool H2DReader::load_internal(FILE *f, Mesh *mesh, const char *filename) { int i, j, k, n; Node* en; bool debug = false; mesh->free(); // parse the file mesh_parser_init(f, filename); mesh_parser_run(debug); fclose(f); //// vertices //////////////////////////////////////////////////////////////// MSymbol* sym = mesh_parser_find_symbol("vertices"); if (sym == NULL) error("File %s: 'vertices' not found.", filename); n = sym->data->n; if (n < 0) error("File %s: 'vertices' must be a list.", filename); if (n < 2) error("File %s: invalid number of vertices.", filename); // create a hash table large enough int size = HashTable::H2D_DEFAULT_HASH_SIZE; while (size < 8*n) size *= 2; mesh->init(size); // create top-level vertex nodes MItem* pair = sym->data->list; for (i = 0; i < n; i++, pair = pair->next) { Node* node = mesh->nodes.add(); assert(node->id == i); node->ref = TOP_LEVEL_REF; node->type = H2D_TYPE_VERTEX; node->bnd = 0; node->p1 = node->p2 = -1; node->next_hash = NULL; if (!mesh_parser_get_doubles(pair, 2, &node->x, &node->y)) error("File %s: invalid vertex #%d.", filename, i); } mesh->ntopvert = n; //// elements //////////////////////////////////////////////////////////////// sym = mesh_parser_find_symbol("elements"); if (sym == NULL) error("File %s: 'elements' not found.", filename); n = sym->data->n; if (n < 0) error("File %s: 'elements' must be a list.", filename); if (n < 1) error("File %s: no elements defined.", filename); // create elements MItem* elem = sym->data->list; mesh->nactive = 0; for (i = 0; i < n; i++, elem = elem->next) { // read and check vertex indices int nv = elem->n, idx[5]; if (!nv) { mesh->elements.skip_slot(); continue; } if (nv < 4 || nv > 5) error("File %s: element #%d: wrong number of vertex indices.", filename, i); if (!mesh_parser_get_ints(elem, nv, &idx[0], &idx[1], &idx[2], &idx[3], &idx[4])) error("File %s: invalid definition of element #%d.", filename, i); for (j = 0; j < nv-1; j++) if (idx[j] < 0 || idx[j] >= mesh->ntopvert) error("File %s: error creating element #%d: vertex #%d does not exist.", filename, i, idx[j]); // create triangle/quad Node *v0 = &mesh->nodes[idx[0]], *v1 = &mesh->nodes[idx[1]], *v2 = &mesh->nodes[idx[2]]; if (nv == 4) { check_triangle(i, v0, v1, v2); mesh->create_triangle(idx[3], v0, v1, v2, NULL); } else { Node *v3 = &mesh->nodes[idx[3]]; check_quad(i, v0, v1, v2, v3); mesh->create_quad(idx[4], v0, v1, v2, v3, NULL); } mesh->nactive++; } mesh->nbase = n; //// boundaries ////////////////////////////////////////////////////////////// sym = mesh_parser_find_symbol("boundaries"); if (sym != NULL) { n = sym->data->n; if (n < 0) error("File %s: 'boundaries' must be a list.", filename); // read boundary data MItem* triple = sym->data->list; for (i = 0; i < n; i++, triple = triple->next) { int v1, v2, marker; if (!mesh_parser_get_ints(triple, 3, &v1, &v2, &marker)) error("File %s: invalid boundary data #%d.", filename, i); en = mesh->peek_edge_node(v1, v2); if (en == NULL) error("File %s: boundary data #%d: edge %d-%d does not exist", filename, i, v1, v2); en->marker = marker; if (marker > 0) { mesh->nodes[v1].bnd = 1; mesh->nodes[v2].bnd = 1; en->bnd = 1; } } } // check that all boundary edges have a marker assigned for_all_edge_nodes(en, mesh) if (en->ref < 2 && en->marker == 0) warn("Boundary edge node does not have a boundary marker"); //// curves ////////////////////////////////////////////////////////////////// sym = mesh_parser_find_symbol("curves"); if (sym != NULL) { n = sym->data->n; if (n < 0) error("File %s: 'curves' must be a list.", filename); // load curved edges MItem* curve = sym->data->list; for (i = 0; i < n; i++, curve = curve->next) { // load the control points, knot vector, etc. Node* en; int p1, p2; Nurbs* nurbs = load_nurbs(mesh, curve, i, &en, p1, p2); // assign the nurbs to the elements sharing the edge node for (k = 0; k < 2; k++) { Element* e = en->elem[k]; if (e == NULL) continue; if (e->cm == NULL) { e->cm = new CurvMap; memset(e->cm, 0, sizeof(CurvMap)); e->cm->toplevel = 1; e->cm->order = 4; } int idx = -1; for (j = 0; j < e->nvert; j++) if (e->en[j] == en) { idx = j; break; } assert(idx >= 0); if (e->vn[idx]->id == p1) { e->cm->nurbs[idx] = nurbs; nurbs->ref++; } else { Nurbs* nurbs_rev = mesh->reverse_nurbs(nurbs); e->cm->nurbs[idx] = nurbs_rev; nurbs_rev->ref++; } } if (!nurbs->ref) delete nurbs; } } // update refmap coeffs of curvilinear elements Element* e; for_all_elements(e, mesh) if (e->cm != NULL) e->cm->update_refmap_coeffs(e); //// refinements ///////////////////////////////////////////////////////////// sym = mesh_parser_find_symbol("refinements"); if (sym != NULL) { n = sym->data->n; if (n < 0) error("File %s: 'refinements' must be a list.", filename); // perform initial refinements MItem* pair = sym->data->list; for (i = 0; i < n; i++, pair = pair->next) { int id, ref; if (!mesh_parser_get_ints(pair, 2, &id, &ref)) error("File %s: invalid refinement #%d.", filename, i); mesh->refine_element(id, ref); } } mesh->ninitial = mesh->elements.get_num_items(); mesh_parser_free(); mesh->seq = g_mesh_seq++; return true; }
bool H2DReader::load_stream(std::istream &is, Mesh *mesh, const char *filename) { int i, j, k, n; Node* en; bool debug = false; mesh->free(); // parse the file // the internal mesh_parser_init only works with C FILE, so we create the // FILE handle from istream using fmemopen. std::string mesh_str = read_file(is); FILE* f = fmemopen((void *) (mesh_str.c_str()), mesh_str.length(), "r"); if (f == NULL) error("Could not create the read buffer"); mesh_parser_init(f, filename); mesh_parser_run(debug); fclose(f); //// vertices //////////////////////////////////////////////////////////////// MSymbol* sym = mesh_parser_find_symbol("vertices"); if (sym == NULL) error("File %s: 'vertices' not found.", filename); n = sym->data->n; if (n < 0) error("File %s: 'vertices' must be a list.", filename); if (n < 2) error("File %s: invalid number of vertices.", filename); // create a hash table large enough int size = HashTable::H2D_DEFAULT_HASH_SIZE; while (size < 8*n) size *= 2; mesh->init(size); // create top-level vertex nodes MItem* pair = sym->data->list; for (i = 0; i < n; i++, pair = pair->next) { Node* node = mesh->nodes.add(); assert(node->id == i); node->ref = TOP_LEVEL_REF; node->type = HERMES_TYPE_VERTEX; node->bnd = 0; node->p1 = node->p2 = -1; node->next_hash = NULL; if (!mesh_parser_get_doubles(pair, 2, &node->x, &node->y)) error("File %s: invalid vertex #%d.", filename, i); } mesh->ntopvert = n; mitem_drop_string_markers(sym->data); //// elements //////////////////////////////////////////////////////////////// sym = mesh_parser_find_symbol("elements"); if (sym == NULL) error("File %s: 'elements' not found.", filename); n = sym->data->n; if (n < 0) error("File %s: 'elements' must be a list.", filename); if (n < 1) error("File %s: no elements defined.", filename); // create elements MItem* elem = sym->data->list; mesh->nactive = 0; for (i = 0; i < n; i++, elem = elem->next) { // read and check vertex indices int nv = elem->n, idx[5]; if (!nv) { mesh->elements.skip_slot(); continue; } if (nv < 4 || nv > 5) error("File %s: element #%d: wrong number of vertex indices.", filename, i); if (!mesh_parser_get_ints(elem, nv, &idx[0], &idx[1], &idx[2], &idx[3], &idx[4])) error("File %s: invalid definition of element #%d.", filename, i); for (j = 0; j < nv-1; j++) if (idx[j] < 0 || idx[j] >= mesh->ntopvert) error("File %s: error creating element #%d: vertex #%d does not exist.", filename, i, idx[j]); Node *v0 = &mesh->nodes[idx[0]], *v1 = &mesh->nodes[idx[1]], *v2 = &mesh->nodes[idx[2]]; int marker; // If we are dealing with a string as a marker. if(elem->marker->size() > 0) { // Number of vertices + the marker is 1 bigger than in the previous context. nv += 1; // This functions check if the user-supplied marker on this element has been // already used, and if not, inserts it in the appropriate structure. mesh->markers_conversion->insert_element_marker(mesh->markers_conversion->min_element_marker_unused, *elem->marker); marker = mesh->markers_conversion->get_internal_element_marker(*elem->marker); } else { if(nv == 4) { // If we have some string-labeled boundary markers. if(mesh->markers_conversion != NULL) { // We need to make sure that the internal markers do not collide. mesh->markers_conversion->check_element_marker(idx[3]); mesh->markers_conversion->insert_element_marker(idx[3], ""); } marker = idx[3]; } else { // If we have some string-labeled boundary markers. if(mesh->markers_conversion != NULL) { // We need to make sure that the internal markers do not collide. mesh->markers_conversion->check_element_marker(idx[4]); mesh->markers_conversion->insert_element_marker(idx[4], ""); } marker = idx[4]; } } if(nv == 4) { check_triangle(i, v0, v1, v2); mesh->create_triangle(marker, v0, v1, v2, NULL); } else { Node *v3 = &mesh->nodes[idx[3]]; check_quad(i, v0, v1, v2, v3); mesh->create_quad(marker, v0, v1, v2, v3, NULL); } mesh->nactive++; } mesh->nbase = n; mitem_drop_string_markers(sym->data); //// boundaries ////////////////////////////////////////////////////////////// sym = mesh_parser_find_symbol("boundaries"); if (sym != NULL) { n = sym->data->n; if (n < 0) error("File %s: 'boundaries' must be a list.", filename); // read boundary data MItem* triple = sym->data->list; for (i = 0; i < n; i++, triple = triple->next) { int v1, v2, marker; if (!mesh_parser_get_ints(triple, triple->n, &v1, &v2, &marker)) error("File %s: invalid boundary data #%d.", filename, i); en = mesh->peek_edge_node(v1, v2); if (en == NULL) error("File %s: boundary data #%d: edge %d-%d does not exist", filename, i, v1, v2); int marker_to_set; // If we are dealing with a string as a marker. if(triple->marker->size() > 0) { // This functions check if the user-supplied marker on this element has been // already used, and if not, inserts it in the appropriate structure. mesh->markers_conversion->insert_boundary_marker(mesh->markers_conversion->min_boundary_marker_unused, *triple->marker); marker_to_set = mesh->markers_conversion->get_internal_boundary_marker(*triple->marker); } else { // If we have some string-labeled boundary markers. if(mesh->markers_conversion != NULL) { // We need to make sure that the internal markers do not collide. mesh->markers_conversion->check_boundary_marker(marker); mesh->markers_conversion->insert_boundary_marker(marker, ""); } marker_to_set = marker; } en->marker = marker_to_set; // This is extremely important, as in DG, it is assumed that negative boundary markers are reserved // for the inner edges. if (marker_to_set > 0) { mesh->nodes[v1].bnd = 1; mesh->nodes[v2].bnd = 1; en->bnd = 1; } } } // check that all boundary edges have a marker assigned for_all_edge_nodes(en, mesh) if (en->ref < 2 && en->marker == 0) { warn("Boundary edge node does not have a boundary marker"); } mitem_drop_string_markers(sym->data); //// curves ////////////////////////////////////////////////////////////////// sym = mesh_parser_find_symbol("curves"); if (sym != NULL) { n = sym->data->n; if (n < 0) error("File %s: 'curves' must be a list.", filename); // load curved edges MItem* curve = sym->data->list; for (i = 0; i < n; i++, curve = curve->next) { // load the control points, knot vector, etc. Node* en; int p1, p2; Nurbs* nurbs = load_nurbs(mesh, curve, i, &en, p1, p2); // assign the nurbs to the elements sharing the edge node for (k = 0; k < 2; k++) { Element* e = en->elem[k]; if (e == NULL) continue; if (e->cm == NULL) { e->cm = new CurvMap; memset(e->cm, 0, sizeof(CurvMap)); e->cm->toplevel = 1; e->cm->order = 4; } int idx = -1; for (j = 0; j < e->nvert; j++) if (e->en[j] == en) { idx = j; break; } assert(idx >= 0); if (e->vn[idx]->id == p1) { e->cm->nurbs[idx] = nurbs; nurbs->ref++; } else { Nurbs* nurbs_rev = mesh->reverse_nurbs(nurbs); e->cm->nurbs[idx] = nurbs_rev; nurbs_rev->ref++; } } if (!nurbs->ref) delete nurbs; } } // update refmap coeffs of curvilinear elements Element* e; for_all_elements(e, mesh) if (e->cm != NULL) e->cm->update_refmap_coeffs(e); //// refinements ///////////////////////////////////////////////////////////// sym = mesh_parser_find_symbol("refinements"); if (sym != NULL) { n = sym->data->n; if (n < 0) error("File %s: 'refinements' must be a list.", filename); // perform initial refinements MItem* pair = sym->data->list; for (i = 0; i < n; i++, pair = pair->next) { int id, ref; if (!mesh_parser_get_ints(pair, 2, &id, &ref)) error("File %s: invalid refinement #%d.", filename, i); mesh->refine_element(id, ref); } } mesh->ninitial = mesh->elements.get_num_items(); mesh_parser_free(); mesh->seq = g_mesh_seq++; return true; }