Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}