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(); std::string mesh_str = read_file(is); Python p; initpython_reader(); p.exec("from python_reader import read_hermes_format_str"); p.push_str("s", mesh_str); p.exec("vertices, elements, boundaries, curves, refinements" " = read_hermes_format_str(s)"); //// vertices //////////////////////////////////////////////////////////////// p.exec("n = len(vertices)"); n = p.pull_int("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 for (i = 0; i < n; i++) { 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; p.push_int("i", i); p.exec("x, y = vertices[i]"); node->x = p.pull_double("x"); node->y = p.pull_double("y"); } mesh->ntopvert = n; //// elements //////////////////////////////////////////////////////////////// p.exec("n = len(elements)"); n = p.pull_int("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 mesh->nactive = 0; for (i = 0; i < n; i++) { // read and check vertex indices p.push_int("i", i); p.exec("nv = len(elements[i])"); int nv = p.pull_int("nv"); int idx[5]; std::string el_marker; 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 (nv == 4) { p.exec("n1, n2, n3, marker = elements[i]"); idx[0] = p.pull_int("n1"); idx[1] = p.pull_int("n2"); idx[2] = p.pull_int("n3"); p.exec("marker_str = 1 if isinstance(marker, str) else 0"); if (p.pull_int("marker_str")) el_marker = p.pull_str("marker"); else { std::ostringstream string_stream; string_stream << p.pull_int("marker"); el_marker = string_stream.str(); } } else { p.exec("n1, n2, n3, n4, marker = elements[i]"); idx[0] = p.pull_int("n1"); idx[1] = p.pull_int("n2"); idx[2] = p.pull_int("n3"); idx[3] = p.pull_int("n4"); p.exec("marker_str = 1 if isinstance(marker, str) else 0"); if (p.pull_int("marker_str")) el_marker = p.pull_str("marker"); else { std::ostringstream string_stream; string_stream << p.pull_int("marker"); el_marker = string_stream.str(); } } 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; // 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->element_markers_conversion.insert_marker(mesh->element_markers_conversion.min_marker_unused, el_marker); marker = mesh->element_markers_conversion.get_internal_marker(el_marker); if(nv == 4) { check_triangle(i, v0, v1, v2); create_triangle(mesh, marker, v0, v1, v2, NULL); } else { Node *v3 = &mesh->nodes[idx[3]]; check_quad(i, v0, v1, v2, v3); create_quad(mesh, marker, v0, v1, v2, v3, NULL); } mesh->nactive++; } mesh->nbase = n; //// boundaries ////////////////////////////////////////////////////////////// p.exec("have_boundaries = 1 if boundaries else 0"); if (p.pull_int("have_boundaries")) { p.exec("n = len(boundaries)"); n = p.pull_int("n"); // read boundary data for (i = 0; i < n; i++) { int v1, v2, marker; p.push_int("i", i); p.exec("v1, v2, marker = boundaries[i]"); v1 = p.pull_int("v1"); v2 = p.pull_int("v2"); 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); std::string bnd_marker; p.exec("marker_str = 1 if isinstance(marker, str) else 0"); if (p.pull_int("marker_str")) bnd_marker = p.pull_str("marker"); else { std::ostringstream string_stream; string_stream << p.pull_int("marker"); bnd_marker = string_stream.str(); } // 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->boundary_markers_conversion.insert_marker(mesh->boundary_markers_conversion.min_marker_unused, bnd_marker); marker = mesh->boundary_markers_conversion.get_internal_marker(bnd_marker); en->marker = marker; // This is extremely important, as in DG, it is assumed that negative boundary markers are reserved // for the inner edges. if (marker > 0) { mesh->nodes[v1].bnd = 1; mesh->nodes[v2].bnd = 1; en->bnd = 1; } } } #ifdef HERMES_COMMON_CHECK_BOUNDARY_CONDITIONS // 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"); } #endif //// curves ////////////////////////////////////////////////////////////////// p.exec("have_curves = 1 if curves else 0"); if (p.pull_int("have_curves")) { p.exec("n = len(curves)"); n = p.pull_int("n"); if (n < 0) error("File %s: 'curves' must be a list.", filename); // load curved edges for (i = 0; i < n; i++) { // load the control points, knot vector, etc. Node* en; int p1, p2; p.push_int("i", i); p.exec("curve = curves[i]"); Nurbs* nurbs = load_nurbs(mesh, p, 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 (unsigned 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 ///////////////////////////////////////////////////////////// p.exec("have_refinements = 1 if refinements else 0"); if (p.pull_int("have_refinements")) { p.exec("n = len(refinements)"); n = p.pull_int("n"); if (n < 0) error("File %s: 'refinements' must be a list.", filename); // perform initial refinements for (i = 0; i < n; i++) { int id, ref; p.push_int("i", i); p.exec("id, ref = refinements[i]"); id = p.pull_int("id"); ref = p.pull_int("ref"); mesh->refine_element_id(id, ref); } } mesh->ninitial = mesh->elements.get_num_items(); mesh->seq = g_mesh_seq++; return true; }
/* Loads the mesh from a stream. */ void H2DReader::load_stream(FILE *f, Mesh *mesh) { int i, j, k, n, maj, min; char* line; // check file version if ((line = get_line(f)) == NULL) eof_error; if (sscanf(line, "%d %d", &maj, &min) != 2) error("Could not read file version"); if (maj > 1) error("Unsupported file version"); // read the number of vertices if ((line = get_line(f)) == NULL) eof_error; if (sscanf(line, "%d", &n) != 1) error("Could not read the number of vertices"); // free all current data mesh->free(); // create a hash table large enough int size = HashTable::H2D_DEFAULT_HASH_SIZE; while (size < 8*n) size *= 2; mesh->init(size); // load vertices: create top-level vertex nodes for (i = 0; i < n; i++) { 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 ((line = get_line(f)) == NULL) eof_error; if (sscanf(line, "%lf %lf", &node->x, &node->y) != 2) error("Error reading vertex data"); } mesh->ntopvert = n; // read the number of elements if ((line = get_line(f)) == NULL) eof_error; if (sscanf(line, "%d", &n) != 1) error("Could not read the number of elements"); // load elements for (i = 0; i < n; i++) { if ((line = get_line(f)) == NULL) eof_error; int ret, idx[5]; if ((ret = sscanf(line, "%d %d %d %d %d", idx, idx+1, idx+2, idx+3, idx+4)) != 4 && ret != 5) error("Error reading elements"); for (j = 0; j < ret-1; j++) if (idx[j] < 0 || idx[j] >= mesh->ntopvert) error("Error reading elements: node %d does not exist", idx[j]); Node *v0 = &mesh->nodes[idx[0]], *v1 = &mesh->nodes[idx[1]], *v2 = &mesh->nodes[idx[2]]; if (ret == 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->nbase = mesh->nactive = n; // read the number of boundary data if ((line = get_line(f)) == NULL) eof_error; if (sscanf(line, "%d", &n) != 1) error("Could not read the number of boundary markers\n"); // load boundary data Node* en; for (i = 0; i < n; i++) { if ((line = get_line(f)) == NULL) eof_error; int v1, v2, marker; if (sscanf(line, "%d %d %d", &v1, &v2, &marker) != 3) error("Error reading boundary marker data"); en = mesh->peek_edge_node(v1, v2); if (en == NULL) error("Boundary data error (edge %d-%d does not exist)", 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"); // read the number of curved edges if ((line = get_line(f)) == NULL) eof_error; if (sscanf(line, "%d", &n) != 1) error("Could not read the number of curved edges"); // load curved edges for (i = 0; i < n; i++) { // load the control points, knot vector, etc. Node* en; int p1, p2; Nurbs* nurbs = load_nurbs_old(mesh, f, &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; } // read the number of initial refinements //if () eof_error; //if (sscanf(line, "%d", &n) != 1) error("could not read the number of initial refinements"); if ((line = get_line(f)) == NULL || sscanf(line, "%d", &n) != 1) { warn("Could not read the number of initial refinements"); } else { // perform initial refinements for (i = 0; i < n; i++) { if ((line = get_line(f)) == NULL) eof_error; int id, ref; if (sscanf(line, "%d %d", &id, &ref) != 2) error("Error reading initial refinement data"); mesh->refine_element(id, ref); } } mesh->ninitial = mesh->elements.get_num_items(); // update refmap coeffs of curvilinear elements Element* e; for_all_elements(e, mesh) if (e->cm != NULL) e->cm->update_refmap_coeffs(e); fclose(f); mesh->seq = g_mesh_seq++; }
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; }