Example #1
0
static mesh_s *make_player_mesh()
{
    mesh_s *mesh = mesh_new();

    // shader
    GLuint shaders[2];
    shaders[0] = graphics_create_shader_from_file(
                     GL_VERTEX_SHADER, "ship.v.glsl");
    shaders[1] = graphics_create_shader_from_file(
                     GL_FRAGMENT_SHADER, "ship.f.glsl");
    mesh_set_program(mesh, graphics_create_program(2, shaders));

    // geometry
    obj_s *obj = obj_load("ship.obj");
    mesh_set_attribute(mesh, "position", 3,
                       obj_get_vertex_count(obj) * 3 * sizeof(float),
                       obj_get_vertices(obj));
    mesh_set_elements(mesh,
                      obj_get_triangle_count(obj) * 3 * sizeof(unsigned),
                      obj_get_triangles(obj));
    obj_release(obj);

    return mesh;
}
Example #2
0
File: mpg.c Project: lazyEagles/rpg
int main (int argc, char *argv[]) {
  if (argc != 10) {
    fprintf(stderr, "Format: ./mpg num0 num1 ... num8\n");
    exit(1);
  }
  /* select seed for rand() */
  srand(time(NULL));
  int num[9]; /* number of positions in each subrectangular */
  int i;
  for (i = 0; i < 9; i++) {
    num[i] = atoi(argv[i+1]);
  }
  Mesh mesh;
  double xp[4] = {0, 167, 333, 500};
  double yp[4] = {0, 167, 333, 500};
  mesh_new(&mesh, 4, xp, 4, yp);
  int id = 0;
  for (i = 0; i < 9; i++) {
    rand_pos_n_id_in_rect(id, num[i], &mesh.rect[i], 1000, NULL, 1);
    id += num[i];
  }
  mesh_free(&mesh);
  return 0;
}
Example #3
0
int test_element( int argc, char *argv[] )
{
    Element *e = element_new();
    g_return_val_if_fail( e->adjacent_halfedge == NULL , 1 );
    element_free( e );

    Point2 p1, p2, p3;
    point2_set( &p1, 0.0, 1.0 );
    point2_set( &p2, 0.0, 0.0 );
    point2_set( &p3, sqrt( 3.0 ), 0.0 );

    gdouble a1, a2, a3;
    triangle_angles( &p1, &p2, &p3, &a1, &a2, &a3 );
    g_return_val_if_fail( fabs( a1 - G_PI/3.0) < SMALL_NUMBER, 1 );
    g_return_val_if_fail( fabs( a2 - G_PI/2.0) < SMALL_NUMBER, 1 );
    g_return_val_if_fail( fabs( a3 - G_PI/6.0) < SMALL_NUMBER, 1 );

    a1 = triangle_circumcircle_radius( &p1, &p2, &p3 );
    g_return_val_if_fail( fabs( a1 - 1.0 ) < SMALL_NUMBER, 1 );

    a1 = triangle_circumcircle_radius_edge_length( 1.0, sqrt( 3.0 ), 2.0 );
    g_return_val_if_fail( fabs( a1 - 1.0 ) < SMALL_NUMBER, 1 );

    Point2 p;
    triangle_circumcenter_coordinates( &p1, &p2, &p3, &p );
    g_return_val_if_fail( fabs( p.x - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1 );
    g_return_val_if_fail( fabs( p.y - 1.0/2.0 ) < SMALL_NUMBER, 1 );

    a1 = triangle_area( &p1, &p2, &p3 );
    g_return_val_if_fail( fabs( a1 - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1 );


    Mesh *mesh = mesh_new();
    Node *n1 = mesh_add_node( mesh, 0.0, 1.0 );
    Node *n2 = mesh_add_node( mesh, 0.0, 0.0 );
    Node *n3 = mesh_add_node( mesh, sqrt(3.0), 0.0 );
    Edge *e1 = mesh_add_edge( mesh, n1, n2 );
    Edge *e2 = mesh_add_edge( mesh, n2, n3 );
    Edge *e3 = mesh_add_edge( mesh, n3, n1 );
    Element *el = mesh_add_element( mesh, &e1->he[0], &e2->he[0], &e3->he[0] );

    gdouble l1, l2, l3;
    element_edge_lengths( el, &l1, &l2, &l3 );
    g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( l2 - sqrt(3.0)) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( l3 - 2.0) < SMALL_NUMBER, 1);

    HalfEdge *he = element_min_edge( el, &l1 );
    g_return_val_if_fail( he->edge == e1, 1 );
    g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1);

    l1 = element_min_edge_length( el );
    g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1);

    he = element_max_edge( el, &l1 );
    g_return_val_if_fail( he->edge == e3, 1 );
    g_return_val_if_fail( fabs( l1 - 2.0) < SMALL_NUMBER, 1);

    l1 = element_max_edge_length( el );
    g_return_val_if_fail( fabs( l1 - 2.0) < SMALL_NUMBER, 1);

    element_angles( el, &a1, &a2, &a3 );
    g_return_val_if_fail( fabs( a1 - G_PI/3.0) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( a2 - G_PI/2.0) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( a3 - G_PI/6.0) < SMALL_NUMBER, 1);

    a1 = element_maximum_angle( el );
    g_return_val_if_fail( fabs( a1 - G_PI/2.0) < SMALL_NUMBER, 1);

    a1 = element_minimum_angle( el );
    g_return_val_if_fail( fabs( a1 - G_PI/6.0) < SMALL_NUMBER, 1);

    element_circumcenter_coordinates( el, &p );
    g_return_val_if_fail( fabs( p.x - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( p.y - 1.0/2.0 ) < SMALL_NUMBER, 1);

    point2_set( NODE_POSITION( n3 ), 3.0, 0.0 );
    a1 = element_area( el );
    g_return_val_if_fail( fabs( a1 - 3.0/2.0) < SMALL_NUMBER, 1);

    return 0;
}
Example #4
0
int main(int argc, char **argv)
{
  fail_unless(!e3x_init(NULL)); // random seed
  
  mesh_t meshA = mesh_new();
  fail_unless(meshA);
  lob_t keyA = lob_new();
  lob_set(keyA,"1a",A_KEY);
  lob_t secA = lob_new();
  lob_set(secA,"1a",A_SEC);
  fail_unless(!mesh_load(meshA,secA,keyA));
  mesh_on_discover(meshA,"auto",mesh_add);

  lob_t keyB = lob_new();
  lob_set(keyB,"1a",B_KEY);
  hashname_t hnB = hashname_vkeys(keyB);
  fail_unless(hnB);
  link_t linkAB = link_get(meshA,hnB);
  fail_unless(linkAB);
  
  netA = tmesh_new(meshA, "test", NULL);
  fail_unless(netA);
  
  netA->sort = driver_sort;
  netA->schedule = driver_schedule;
  netA->advance = driver_advance;
  netA->medium = driver_medium;
  netA->free = driver_free;
  
  fail_unless(netA->knock);
  fail_unless(strcmp(netA->community,"test") == 0);

  // create outgoing beacon
  fail_unless(tmesh_schedule(netA,1));
  fail_unless(netA->beacon);
  fail_unless(!netA->beacon->frames);
  fail_unless(!netA->beacon->mote);
  fail_unless(netA->beacon->medium == 1);

  // should have schedule a beacon rx
  fail_unless(scheduled == 1);
  fail_unless(netA->knock->is_active);
  fail_unless(netA->knock->tempo == netA->beacon);
  fail_unless(netA->knock->tempo->at == 2);
  fail_unless(netA->knock->tempo->chan == 1);

  mote_t moteB = tmesh_mote(netA, linkAB);
  fail_unless(moteB);
  fail_unless(moteB->link == linkAB);
  fail_unless(moteB->signal);
  fail_unless(moteB->signal->medium == 1);
  fail_unless(moteB->signal->driver == (void*)1);

  /*
  cmnty_t c = tmesh_join(netA,"qzjb5f4t","foo");
  fail_unless(c);
  fail_unless(c->medium->bin[0] == 134);
  fail_unless(c->medium->radio == devA->id);
  fail_unless(c->beacons == NULL);
  fail_unless(c->pipe->path);
  LOG("netA %.*s",c->pipe->path->head_len,c->pipe->path->head);
  fail_unless(tmesh_leave(netA,c));

  char hex[256];
  netA->last = 1;
  fail_unless(!tmesh_join(netA, "azdhpa5r", NULL));
  fail_unless((c = tmesh_join(netA, "azdhpa5n", "Public")));
  fail_unless(c->beacons);
  fail_unless(c->beacons->public);
  mote_t m = c->beacons;
  mote_t mpub = m;
  memset(m->nonce,42,8); // nonce is random, force stable for fixture testing
  LOG("nonce %s",util_hex(m->nonce,8,hex));
  fail_unless(util_cmp(hex,"2a2a2a2a2a2a2a2a") == 0);
  LOG("public at is now %lu",c->beacons->at);

  m = tmesh_link(netA, c, link);
  fail_unless(m);
  fail_unless(m->link == link);
  fail_unless(m == tmesh_link(netA, c, link));
  fail_unless(m->order == 0);
  memset(m->nonce,3,8); // nonce is random, force stable for fixture testing
  LOG("secret %s",util_hex(m->secret,32,hex));
  fail_unless(util_cmp(hex,"b7bc9e4f1f128f49a3bcef321450b996600987b129723cc7ae752d6500883c65") == 0);
  LOG("public at is now %lu",mpub->at);
  
  fail_unless(mote_reset(m));
  memset(m->nonce,0,8); // nonce is random, force stable for fixture testing
  knock_t knock = devA->knock;
  fail_unless(mote_advance(m));
  LOG("next is %lld",m->at);
  fail_unless(m->at == 8369);
  fail_unless(mote_knock(m,knock));
  fail_unless(!knock->tx);
  fail_unless(mote_advance(m));
  fail_unless(mote_advance(m));
  fail_unless(mote_advance(m));
  fail_unless(mote_advance(m));
  fail_unless(mote_knock(m,knock));
  fail_unless(knock->tx);
  LOG("next is %lld",knock->start);
  fail_unless(knock->start == 29905);
  LOG("public at is now %lu",mpub->at);
  fail_unless(mpub->at == 1);
  mpub->at = 5;

  mote_t bm = tmesh_seek(netA,c,link->id);
  memset(bm->nonce,2,8); // nonce is random, force stable for fixture testing
  mote_reset(m);
  memset(m->nonce,2,8); // nonce is random, force stable for fixture testing
  m->at = 10;
  fail_unless(tmesh_process(netA,1,1));
  fail_unless(m->at == 9);
  fail_unless(knock->mote == mpub);

  LOG("tx %d start %lld stop %lld chan %d at %lld",knock->tx,knock->start,knock->stop,knock->chan,m->at);
  fail_unless(!knock->tx);
  fail_unless(knock->start == 4);
  fail_unless(knock->stop == 4+1000);
  fail_unless(knock->chan == 27);
//  fail_unless(tmesh_knocked(netA,knock));
  LOG("public at is now %lu",c->beacons->at);
  
  fail_unless(mote_advance(m));
  LOG("seek %s",util_hex(m->nonce,8,hex));
  fail_unless(util_cmp(hex,"dc09a8ca7f5cb75e") == 0);
  fail_unless(mote_advance(m));
  LOG("at is %lu",m->at);
  fail_unless(m->at >= 6037);

  // public ping now
//  m->at = 0xffffffff;
  memset(knock,0,sizeof(struct knock_struct));
  fail_unless(tmesh_process(netA,8050,0));
  LOG("beacon at is now %lu",bm->at);
  fail_unless(knock->mote == bm);
  LOG("tx %d start %lld stop %lld chan %d",knock->tx,knock->start,knock->stop,knock->chan);
  fail_unless(!knock->tx);
  fail_unless(knock->start == 9040);
  fail_unless(knock->stop == 9040+1000);
  fail_unless(knock->chan == 19);
  
  // TEMP DISABLED
  return 0;

  // public ping tx
  memset(m->nonce,4,8); // fixture for testing
  m->order = 1;
  memset(knock,0,sizeof(struct knock_struct));
  LOG("public at is now %lu",m->at);
  fail_unless(tmesh_process(netA,20000,0));
  fail_unless(knock->mote == bm);
  LOG("tx %d start %lld stop %lld chan %d",knock->tx,knock->start,knock->stop,knock->chan);
  fail_unless(knock->ready);
  fail_unless(knock->tx);
  fail_unless(knock->start == 21128);
  fail_unless(knock->chan == 19);
  // frame would be random ciphered, but we fixed it to test
  LOG("frame %s",util_hex(knock->frame,32+8,hex)); // just the stable part
  fail_unless(util_cmp(hex,"6c265ac8d9a533a1bc7c7f49ed83ae5d32d31b4b9b76c485b182d649c91deb08a160aab63ee8212c") == 0);
  // let's preted it's an rx now
  knock->tx = 0;
  knock->stopped = knock->stop; // fake rx good
  LOG("faking rx in");
  fail_unless(!tmesh_knocked(netA,knock)); // identity crisis
  fail_unless(tmesh_process(netA,42424,0));
  LOG("tx %d start %lld stop %lld chan %d",knock->tx,knock->start,knock->stop,knock->chan);
  fail_unless(knock->stopped);
  fail_unless(knock->start == 43444);

  // leave public community
  fail_unless(tmesh_leave(netA,c));
  
  // two motes meshing
  mesh_t meshB = mesh_new();
  fail_unless(meshB);
  lob_t secB = lob_new();
  lob_set(secB,"1a",B_SEC);
  fail_unless(!mesh_load(meshB,secB,keyB));
  mesh_on_discover(meshB,"auto",mesh_add);

  hashname_t hnA = hashname_vkeys(keyA);
  fail_unless(hnA);
  link_t linkBA = link_get(meshB,hnA);
  fail_unless(linkBA);
  
  netB = tmesh_new(meshB, NULL);
  fail_unless(netB);
  cmnty_t cB = tmesh_join(netB,"qzjb5f4t","test");
  fail_unless(cB);
  fail_unless(cB->pipe->path);
  LOG("netB %s",lob_json(cB->pipe->path));

  cmnty_t cA = tmesh_join(netA,"qzjb5f4t","test");
  fail_unless(cA);
  fail_unless(cA->pipe->path);
  LOG("netA %s",lob_json(cA->pipe->path));
  
  mote_t bmBA = tmesh_seek(netB, cB, linkBA->id);
  fail_unless(bmBA);
  fail_unless(bmBA->order == 1);
  LOG("bmBA %s secret %s",hashname_short(bmBA->beacon),util_hex(bmBA->secret,32,hex));
  fail_unless(util_cmp(hex,"9a972d28dcc211d43eafdca7877bed1bbeaec30fd3740f4b787355d10423ad12") == 0);

  mote_t mBA = tmesh_link(netB, cB, linkBA);
  fail_unless(mBA);
  fail_unless(mBA->order == 1);
  LOG("mBA %s secret %s",hashname_short(mBA->link->id),util_hex(mBA->secret,32,hex));
  fail_unless(util_cmp(hex,"9a972d28dcc211d43eafdca7877bed1bbeaec30fd3740f4b787355d10423ad12") == 0);

  mote_t bmAB = tmesh_seek(netA, cA, link->id);
  fail_unless(bmAB);
  fail_unless(bmAB->order == 0);
  LOG("bmBA %s secret %s",hashname_short(bmAB->beacon),util_hex(bmAB->secret,32,hex));
  fail_unless(util_cmp(hex,"9a972d28dcc211d43eafdca7877bed1bbeaec30fd3740f4b787355d10423ad12") == 0);

  mote_t mAB = tmesh_link(netA, cA, link);
  fail_unless(mAB);
  fail_unless(mAB->order == 0);
  LOG("mAB %s secret %s",hashname_short(mAB->link->id),util_hex(mAB->secret,32,hex));
  fail_unless(util_cmp(hex,"9a972d28dcc211d43eafdca7877bed1bbeaec30fd3740f4b787355d10423ad12") == 0);
  
  knock_t knBA = devB->knock;
  knBA->ready = 0;
  memset(mBA->nonce,0,8);
  memset(bmBA->nonce,2,8);
  fail_unless(tmesh_process(netB,10,0));
  fail_unless(knBA->mote == bmBA);
  LOG("BA tx is %d chan %d at %lu",knBA->tx,knBA->chan,knBA->start);
  fail_unless(knBA->chan == 35);
  fail_unless(knBA->tx == 0);

  knock_t knAB = devA->knock;
  knAB->ready = 0;
  memset(mAB->nonce,10,8);
  memset(bmAB->nonce,15,8);
  fail_unless(tmesh_process(netA,44444,0));
  fail_unless(knAB->mote == bmAB);
  LOG("AB tx is %d chan %d at %lu nonce %s",knAB->tx,knAB->chan,knAB->start,util_hex(mAB->nonce,8,NULL));
  fail_unless(knAB->chan == 35);
  fail_unless(knAB->tx == 1);

  // fake reception, with fake cake
  LOG("process netA");
  RXTX(knAB,knBA);
  fail_unless(tmesh_knocked(netA,knAB));
  fail_unless(tmesh_process(netA,67689,0));
  fail_unless(knAB->mote == bmAB);
  fail_unless(!bmAB->chunks);

  LOG("process netB");
  RXTX(knAB,knBA);
  fail_unless(tmesh_knocked(netB,knBA));
  fail_unless(tmesh_process(netB,22000,0));

  // dummy data for sync send
  netA->pubim = hashname_im(netA->mesh->keys, hashname_id(netA->mesh->keys,netA->mesh->keys));
  netB->pubim = hashname_im(netB->mesh->keys, hashname_id(netB->mesh->keys,netB->mesh->keys));

  // back to the future
  RXTX(knAB,knBA);
  fail_unless(tmesh_knocked(netA,knAB));
  LOG("mAB %lu mBA %lu",mAB->at,mBA->at);
  while(knBA->mote != bmBA)
  {
    knBA->ready = 0;
    fail_unless(tmesh_process(netB,knBA->stop,0));
  }
  LOG("BA tx is %d chan %d at %lu nonce %s",knBA->tx,knBA->chan,knAB->start,util_hex(mBA->nonce,8,NULL));
//  fail_unless(knBA->tx == 1);

  RXTX(knAB,knBA);
  LOG("mAB %lu mBA %lu",mAB->at,mBA->at);
  fail_unless(tmesh_knocked(netB,knBA));
  while(knAB->mote != bmAB)
  {
    knAB->ready = 0;
    fail_unless(tmesh_process(netA,knAB->stop,0));
  }
  LOG("AB tx is %d chan %d at %lu nonce %s",knAB->tx,knAB->chan,knAB->start,util_hex(mAB->nonce,8,NULL));
//  fail_unless(knAB->tx == 0);

  // in sync!
  fail_unless(!mBA->chunks);
  fail_unless(!mAB->chunks);
  mAB->at = mBA->at;
  LOG("mAB %lu mBA %lu",mAB->at,mBA->at);
  fail_unless(mAB->at == mBA->at);
  
  // continue establishing link
  printf("\n\n");
  int max = 40;
  mote_reset(mAB);
  mote_reset(mBA);
  mote_reset(bmAB);
  mote_reset(bmBA);
  mAB->at = mBA->at;
  bmAB->at = bmBA->at;
  uint32_t step = mAB->at;
  while(--max > 0 && !link_up(mBA->link) && !link_up(mAB->link))
  {
    printf("\n\n%d %u\n",max,step);

    tmesh_process(netA,step,0);
    tmesh_process(netB,step,0);

    LOG("AB %d %d/%d BA %d %d/%d",knAB->tx,knAB->start,knAB->stop,knBA->tx,knBA->start,knBA->stop);
    if(knAB->stop > step) step = knAB->stop;
    if(knBA->stop > step) step = knBA->stop;

    if(knAB->chan == knBA->chan)
    {
      printf("~~~~RXTX %u\n",step);
      RXTX(knAB,knBA);
      knAB->stopped = knAB->stop;
      knBA->stopped = knBA->stop;
    }else{
      knAB->err = knBA->err = 1;
    }

    tmesh_knocked(netA,knAB);
    tmesh_knocked(netB,knBA);

  }
  LOG("TODO linked by %d",max);
//  fail_unless(max);
*/
  return 0;
}
Example #5
0
static mesh_t* create_dual_mesh_from_tet_mesh(MPI_Comm comm, 
                                              mesh_t* tet_mesh,
                                              char** external_model_face_tags,
                                              int num_external_model_face_tags,
                                              char** internal_model_face_tags,
                                              int num_internal_model_face_tags,
                                              char** model_edge_tags,
                                              int num_model_edge_tags,
                                              char** model_vertex_tags,
                                              int num_model_vertex_tags)
{
  // Build sets containing the indices of mesh elements identifying 
  // geometric structure (for ease of querying).

  // External model faces, their edges, and attached tetrahedra.
  int_unordered_set_t* external_boundary_tets = int_unordered_set_new();
  int_unordered_set_t* external_model_faces = int_unordered_set_new();
  int_unordered_set_t* external_model_face_edges = int_unordered_set_new();
  int_unordered_set_t* model_face_nodes = int_unordered_set_new();
  for (int i = 0; i < num_external_model_face_tags; ++i)
  {
    int num_faces;
    int* tag = mesh_tag(tet_mesh->face_tags, external_model_face_tags[i], &num_faces);
    for (int f = 0; f < num_faces; ++f)
    {
      int face = tag[f];
      int_unordered_set_insert(external_model_faces, face);

      int btet1 = tet_mesh->face_cells[2*face];
      int_unordered_set_insert(external_boundary_tets, btet1);
      int btet2 = tet_mesh->face_cells[2*face+1];
      if (btet2 != -1)
        int_unordered_set_insert(external_boundary_tets, btet2);

      int pos = 0, edge, node;
      while (mesh_face_next_edge(tet_mesh, face, &pos, &edge))
        int_unordered_set_insert(external_model_face_edges, edge);
      pos = 0;
      while (mesh_face_next_node(tet_mesh, face, &pos, &node))
        int_unordered_set_insert(model_face_nodes, node);
    }
  }

  // Internal model faces, their edges, and attached tetrahedra.
  int_unordered_set_t* internal_boundary_tets = int_unordered_set_new();
  int_unordered_set_t* internal_model_faces = int_unordered_set_new();
  int_unordered_set_t* internal_model_face_edges = int_unordered_set_new();
  for (int i = 0; i < num_internal_model_face_tags; ++i)
  {
    int num_faces;
    int* tag = mesh_tag(tet_mesh->face_tags, internal_model_face_tags[i], &num_faces);
    for (int f = 0; f < num_faces; ++f)
    {
      int face = tag[f];
      int_unordered_set_insert(internal_model_faces, face);

      int btet1 = tet_mesh->face_cells[2*face];
      int_unordered_set_insert(internal_boundary_tets, btet1);
      int btet2 = tet_mesh->face_cells[2*face+1];
      if (btet2 != -1)
        int_unordered_set_insert(internal_boundary_tets, btet2);

      int pos = 0, edge, node;
      while (mesh_face_next_edge(tet_mesh, face, &pos, &edge))
        int_unordered_set_insert(internal_model_face_edges, edge);
      pos = 0;
      while (mesh_face_next_node(tet_mesh, face, &pos, &node))
        int_unordered_set_insert(model_face_nodes, node);
    }
  }

  // Model edges and nodes belonging to them.
  int_unordered_set_t* model_edges = int_unordered_set_new();
  int_unordered_set_t* model_edge_nodes = int_unordered_set_new();
  for (int i = 0; i < num_model_edge_tags; ++i)
  {
    int num_edges;
    int* tag = mesh_tag(tet_mesh->edge_tags, model_edge_tags[i], &num_edges);
    for (int e = 0; e < num_edges; ++e)
    {
      int edge = tag[e];
      int_unordered_set_insert(model_edges, edge);
      int_unordered_set_insert(model_edge_nodes, tet_mesh->edge_nodes[2*edge]);
      int_unordered_set_insert(model_edge_nodes, tet_mesh->edge_nodes[2*edge+1]);
    }
  }
  int_unordered_set_t* model_vertices = int_unordered_set_new();
  for (int i = 0; i < num_model_vertex_tags; ++i)
  {
    int num_vertices;
    int* tag = mesh_tag(tet_mesh->node_tags, model_vertex_tags[i], &num_vertices);
    for (int v = 0; v < num_vertices; ++v)
    {
      int vertex = tag[v];
      int_unordered_set_insert(model_vertices, vertex);

      // A model vertex should not obey the same rules as a vertex that is 
      // attached to a model edge/face, so remove this vertex from those sets.
      int_unordered_set_delete(model_edge_nodes, vertex);
      int_unordered_set_delete(model_face_nodes, vertex);
    }
  }

  // Each primal edge is surrounded by primal cells and faces, 
  // so we build lists of these cells/faces with which the edges are 
  // associated.
  int_unordered_set_t** primal_cells_for_edge = polymec_malloc(sizeof(int_unordered_set_t*) * tet_mesh->num_edges);
  int_unordered_set_t** primal_faces_for_edge = polymec_malloc(sizeof(int_unordered_set_t*) * tet_mesh->num_edges);
  int_unordered_set_t** primal_boundary_faces_for_node = polymec_malloc(sizeof(int_unordered_set_t*) * tet_mesh->num_nodes);
  memset(primal_cells_for_edge, 0, sizeof(int_unordered_set_t*) * tet_mesh->num_edges);
  memset(primal_faces_for_edge, 0, sizeof(int_unordered_set_t*) * tet_mesh->num_edges);
  memset(primal_boundary_faces_for_node, 0, sizeof(int_unordered_set_t*) * tet_mesh->num_nodes);
  for (int cell = 0; cell < tet_mesh->num_cells; ++cell)
  {
    int pos = 0, face;
    while (mesh_cell_next_face(tet_mesh, cell, &pos, &face))
    {
      int pos1 = 0, edge;
      while (mesh_face_next_edge(tet_mesh, face, &pos1, &edge))
      {
        // Associate the cell with this edge.
        int_unordered_set_t* cells_for_edge = primal_cells_for_edge[edge];
        if (cells_for_edge == NULL)
        {
          cells_for_edge = int_unordered_set_new();
          primal_cells_for_edge[edge] = cells_for_edge;
        }
        int_unordered_set_insert(cells_for_edge, cell);

        // Associate the face with this edge.
        int_unordered_set_t* faces_for_edge = primal_faces_for_edge[edge];
        if (faces_for_edge == NULL)
        {
          faces_for_edge = int_unordered_set_new();
          primal_faces_for_edge[edge] = faces_for_edge;
        }
        int_unordered_set_insert(faces_for_edge, face);
      }

      // If the face is on an internal or external boundary, 
      // associate it with each of the edge's nodes.
      if (int_unordered_set_contains(external_model_faces, face) || 
          int_unordered_set_contains(internal_model_faces, face))
      {
        int pos1 = 0, node;
        while (mesh_face_next_node(tet_mesh, face, &pos1, &node))
        {
          int_unordered_set_t* faces_for_node = primal_boundary_faces_for_node[node];
          if (faces_for_node == NULL)
          {
            faces_for_node = int_unordered_set_new();
            primal_boundary_faces_for_node[node] = faces_for_node;
          }
          int_unordered_set_insert(faces_for_node, face);
        }
      }
    }
  }

  // Count up the dual mesh entities.
  int num_dual_nodes = external_model_faces->size + 
                       internal_model_faces->size + tet_mesh->num_cells + 
                       model_edges->size + model_vertices->size;
  int num_dual_faces_from_boundary_vertices = 0;
  // Dual faces for boundary faces attached to primal nodes.
  for (int n = 0; n < tet_mesh->num_nodes; ++n)
  {
    int_unordered_set_t* boundary_faces_for_node = primal_boundary_faces_for_node[n];
    if (boundary_faces_for_node != NULL)
      num_dual_faces_from_boundary_vertices += boundary_faces_for_node->size;
  }
  {
    // Dual faces for model edges attached to primal nodes.
    int pos = 0, edge;
    while (int_unordered_set_next(model_edges, &pos, &edge))
    {
      int_unordered_set_t* faces_for_edge = primal_faces_for_edge[edge];
      int pos1 = 0, face;
      while (int_unordered_set_next(faces_for_edge, &pos1, &face))
      {
        if (int_unordered_set_contains(external_model_faces, face) || 
            int_unordered_set_contains(internal_model_faces, face))
          ++num_dual_faces_from_boundary_vertices;
      }
    }

    // Dual faces for primal nodes that are model vertices.
    int node;
    pos = 0;
    while (int_unordered_set_next(model_vertices, &pos, &node))
    {
      int_unordered_set_t* boundary_faces_for_node = primal_boundary_faces_for_node[node];
      ASSERT(boundary_faces_for_node != NULL);
      num_dual_faces_from_boundary_vertices += boundary_faces_for_node->size;
    }
  }
  int num_dual_faces = tet_mesh->num_edges + external_model_face_edges->size +
                       num_dual_faces_from_boundary_vertices;
  int num_dual_cells = tet_mesh->num_nodes;
  int num_dual_ghost_cells = 0; 
  // FIXME: Figuring out ghost dual cells probably requires parallel communication.

  // Now that we know the various populations, build the dual mesh.
  mesh_t* dual_mesh = mesh_new(comm, num_dual_cells, num_dual_ghost_cells, 
                               num_dual_faces, num_dual_nodes);

  // Generate dual vertices for each of the interior tetrahedra.
  tetrahedron_t* tet = tetrahedron_new();
  int dv_offset = 0;
  for (int c = 0; c < tet_mesh->num_cells; ++c, ++dv_offset)
  {
    // The dual vertex is located at the circumcenter of the tetrahedral 
    // cell, or the point in the cell closest to it.
    point_t xc;
    tetrahedron_compute_circumcenter(tet, &xc);
    tetrahedron_compute_nearest_point(tet, &xc, &dual_mesh->nodes[dv_offset]);
  }

  // Generate dual vertices for each of the model faces. Keep track of which 
  // faces generated which vertices.
  int_int_unordered_map_t* dual_node_for_model_face = int_int_unordered_map_new();
  for (int i = 0; i < num_external_model_face_tags; ++i)
  {
    int num_faces;
    int* tag = mesh_tag(tet_mesh->face_tags, external_model_face_tags[i], &num_faces);
    for (int f = 0; f < num_faces; ++f, ++dv_offset)
    {
      int face = tag[f];
      dual_mesh->nodes[dv_offset] = tet_mesh->face_centers[face];
      int_int_unordered_map_insert(dual_node_for_model_face, face, dv_offset);
    }
  }
  for (int i = 0; i < num_internal_model_face_tags; ++i)
  {
    int num_faces;
    int* tag = mesh_tag(tet_mesh->face_tags, internal_model_face_tags[i], &num_faces);
    for (int f = 0; f < num_faces; ++f, ++dv_offset)
    {
      int face = tag[f];
      dual_mesh->nodes[dv_offset] = tet_mesh->face_centers[face];
      int_int_unordered_map_insert(dual_node_for_model_face, face, dv_offset);
    }
  }

  // Generate a dual vertex at the midpoint of each model edge.
  int_int_unordered_map_t* dual_node_for_edge = int_int_unordered_map_new();
  for (int i = 0; i < num_model_edge_tags; ++i)
  {
    int num_edges;
    int* tag = mesh_tag(tet_mesh->edge_tags, model_edge_tags[i], &num_edges);
    for (int e = 0; e < num_edges; ++e, ++dv_offset)
    {
      int edge = tag[e];
      point_t* x1 = &tet_mesh->nodes[tet_mesh->edge_nodes[2*edge]];
      point_t* x2 = &tet_mesh->nodes[tet_mesh->edge_nodes[2*edge+1]];
      point_t* n = &dual_mesh->nodes[dv_offset];
      n->x = 0.5 * (x1->x + x2->x);
      n->y = 0.5 * (x1->y + x2->y);
      n->z = 0.5 * (x1->z + x2->z);
      int_int_unordered_map_insert(dual_node_for_edge, e, dv_offset);
    }
  }

  // Generate a dual vertex for each model vertex.
  for (int i = 0; i < num_model_vertex_tags; ++i)
  {
    int num_vertices;
    int* tag = mesh_tag(tet_mesh->node_tags, model_vertex_tags[i], &num_vertices);
    for (int v = 0; v < num_vertices; ++v, ++dv_offset)
    {
      int vertex = tag[v];
      dual_mesh->nodes[dv_offset] = tet_mesh->nodes[vertex];
    }
  }
  ASSERT(dv_offset == num_dual_nodes);

  // Now generate dual faces corresponding to primal edges. 
  int df_offset = 0;
  dual_mesh->face_node_offsets[0] = 0;
  int_array_t** nodes_for_dual_face = polymec_malloc(sizeof(int_array_t*) * num_dual_faces);
  memset(nodes_for_dual_face, 0, sizeof(int_array_t*) * num_dual_faces);
  for (int edge = 0; edge < tet_mesh->num_edges; ++edge)
  {
    int_unordered_set_t* cells_for_edge = primal_cells_for_edge[edge];
    ASSERT(cells_for_edge != NULL);

    // Is this edge a model edge?
    bool is_external_face_edge = int_unordered_set_contains(external_model_face_edges, edge);
    bool is_internal_face_edge = int_unordered_set_contains(internal_model_face_edges, edge);
    bool is_model_edge = int_unordered_set_contains(model_edges, edge);

    if (is_external_face_edge)
    {
      // This primal edge belongs to an external model face,
      // so it lies on the outside of the domain. The corresponding dual 
      // face is bounded by dual nodes created from the primal cells 
      // bounding the edge. We want to order these dual nodes starting at 
      // one boundary cell and finishing at the other. So we extract the 
      // indices of the dual nodes and then pick out the endpoints.
      int num_nodes = cells_for_edge->size;
      int pos = 0, cell, c = 0;
      point_t dual_nodes[num_nodes];
      int dual_node_indices[num_nodes];
      int endpoint_indices[] = {-1, -1};
      while (int_unordered_set_next(cells_for_edge, &pos, &cell))
      {
        dual_nodes[c] = tet_mesh->cell_centers[cell];
        dual_node_indices[c] = cell;
        if (int_unordered_set_contains(external_boundary_tets, cell))
        {
          if (endpoint_indices[0] == -1)
            endpoint_indices[0] = c;
          else
            endpoint_indices[1] = c;
        }
        ++c;
      }

      // Find a vector connecting the nodes of this edge. This orients 
      // the face.
      vector_t edge_vector;
      point_t* x1 = &tet_mesh->nodes[tet_mesh->edge_nodes[2*edge]];
      point_t* x2 = &tet_mesh->nodes[tet_mesh->edge_nodes[2*edge+1]];
      point_displacement(x1, x2, &edge_vector);

      // Order the nodes of this dual face.
      sp_func_t* edge_plane = plane_sp_func_new(&edge_vector, x1);
      order_nodes_of_dual_face(edge_plane, endpoint_indices, dual_nodes, 
          num_nodes, dual_node_indices);

      // Update the dual mesh's face->node connectivity metadata.
      int num_face_nodes = (is_model_edge) ? num_nodes + 1 : num_nodes;
      ASSERT(num_face_nodes >= 3);
      dual_mesh->face_node_offsets[df_offset+1] = dual_mesh->face_node_offsets[df_offset] + num_face_nodes;
      int_array_t* face_nodes = int_array_new();
      nodes_for_dual_face[df_offset] = face_nodes;
      int_array_resize(face_nodes, num_face_nodes);
      memcpy(face_nodes->data, dual_node_indices, sizeof(int)*num_nodes);

      // If the edge is a model edge, stick the primal edge's node at the end 
      // of the list of dual face nodes.
      if (is_model_edge)
      {
        int* dual_node_from_edge_p = int_int_unordered_map_get(dual_node_for_edge, edge);
        ASSERT(dual_node_from_edge_p != NULL);
        int dual_node_from_edge = *dual_node_from_edge_p;
        face_nodes->data[num_nodes] = dual_node_from_edge;
      }
      ++df_offset;
    }
    else if (is_internal_face_edge)
    {
      // This primal edge belongs to an internal model face,
      // so it lies on an interface between two regions within the domain. 
      // We create two dual faces for this edge (one for each region), 
      // using a procedure very similar to the one we used for external 
      // edges above.

      // Dump the IDs of the cells attached to the edge into a single array.
      int num_cells = cells_for_edge->size;
      int pos = 0, cell, c = 0;
      point_t dual_nodes[num_cells];
      int dual_node_indices[num_cells];
      while (int_unordered_set_next(cells_for_edge, &pos, &cell))
      {
        dual_nodes[c] = tet_mesh->cell_centers[cell];
        dual_node_indices[c] = cell;
        ++c;
      }

      // Since this is an internal interface edge, the dual nodes 
      // corresponding to these cells form a polygon around the edge. We can 
      // arrange the nodes for the two faces (stuck together) into a polygon 
      // using the "star" algorithm and then retrieve them (in order) from 
      // the polygon.
      polygon_t* dual_polygon = polygon_giftwrap(dual_nodes, num_cells);
      //        polygon_t* dual_polygon = polygon_star(x0, dual_nodes, num_cells);
      int* ordering = polygon_ordering(dual_polygon);

      // Now we just need to apportion the right nodes to the right faces.
      int start_index1 = -1, start_index2 = -1, stop_index1 = -1, stop_index2 = -1;
      for (int i = 0; i < num_cells; ++i)
      {
        // Follow the cells around the face.
        int this_cell = dual_node_indices[ordering[i]];
        int next_cell = dual_node_indices[ordering[(i+1)%num_cells]];
        if (int_unordered_set_contains(internal_boundary_tets, this_cell) && 
            int_unordered_set_contains(internal_boundary_tets, next_cell))
        {
          // If this_cell and next_cell share a face that is an internal 
          // model face, they are on the opposite side of the interface.
          int shared_face = mesh_cell_face_for_neighbor(tet_mesh, this_cell, next_cell);
          if ((shared_face != -1) && 
              int_unordered_set_contains(internal_model_faces, shared_face))
          {
            if (start_index1 == -1)
            {
              // Face 1 starts on the "next cell," and face 2 ends on 
              // "this cell."
              start_index1 = next_cell;
              stop_index2 = this_cell;
            }
            else
            {
              // Face 2 starts on the "next cell," and face 1 ends on 
              // "this cell."
              start_index2 = next_cell;
              stop_index1 = this_cell;
            }
          }
        }
      }

      // Update the dual mesh's face->node connectivity metadata for 
      // both faces.
      int num_nodes1 = stop_index1 - start_index1 + 1;
      int num_face1_nodes = (is_model_edge) ? num_nodes1 + 1 : num_nodes1;
      ASSERT(num_face1_nodes >= 3);
      dual_mesh->face_node_offsets[df_offset+1] = dual_mesh->face_node_offsets[df_offset] + num_face1_nodes;
      int_array_t* face1_nodes = int_array_new();
      nodes_for_dual_face[df_offset] = face1_nodes;
      int_array_resize(face1_nodes, num_nodes1);
      for (int i = start_index1; i <= stop_index1; ++i)
      {
        int j = (start_index1 + i) % num_cells;
        face1_nodes->data[i] = dual_node_indices[ordering[j]];
      }

      int num_nodes2 = stop_index2 - start_index2 + 1;
      int num_face2_nodes = (is_model_edge) ? num_nodes2 + 1 : num_nodes2;
      ASSERT(num_face2_nodes >= 3);
      dual_mesh->face_node_offsets[df_offset+2] = dual_mesh->face_node_offsets[df_offset+1] + num_face2_nodes;
      int_array_t* face2_nodes = int_array_new();
      nodes_for_dual_face[df_offset+1] = face2_nodes;
      int_array_resize(face2_nodes, num_nodes2);
      for (int i = 0; i <= num_nodes2; ++i)
      {
        int j = (start_index2 + i) % num_cells;
        face1_nodes->data[i] = dual_node_indices[ordering[j]];
      }

      // If the edge is a model edge, stick the primal edge's node at the end 
      // of each of the lists of dual face nodes.
      if (is_model_edge)
      {
        int* dual_node_from_edge_p = int_int_unordered_map_get(dual_node_for_edge, edge);
        ASSERT(dual_node_from_edge_p != NULL);
        int dual_node_from_edge = *dual_node_from_edge_p;
        face1_nodes->data[num_nodes1] = dual_node_from_edge;
        face2_nodes->data[num_nodes2] = dual_node_from_edge;
      }
      df_offset += 2;
    }
    else
    {
      // This edge is on the interior of the domain, so it is only bounded 
      // by cells.

      // Dump the cell centers into an array.
      int num_cells = cells_for_edge->size;
      int pos = 0, cell, c = 0;
      point_t dual_nodes[num_cells];
      while (int_unordered_set_next(cells_for_edge, &pos, &cell))
        dual_nodes[c++] = tet_mesh->cell_centers[cell];

      // Update the dual mesh's connectivity metadata.
      dual_mesh->face_node_offsets[df_offset+1] = dual_mesh->face_node_offsets[df_offset] + num_cells;

      // Since this is an interior edge, the dual nodes corresponding to 
      // these cells form a convex polygon around the edge. We can arrange 
      // the nodes into a convex polygon using the gift-wrapping algorithm.
      polygon_t* dual_polygon = polygon_giftwrap(dual_nodes, num_cells);
      int_array_t* face_nodes = int_array_new();
      int_array_resize(face_nodes, num_cells);
      memcpy(face_nodes->data, polygon_ordering(dual_polygon), sizeof(int)*num_cells);
      nodes_for_dual_face[df_offset] = face_nodes;
      dual_polygon = NULL;
      ++df_offset;
    }
  }
  ASSERT(df_offset == num_dual_faces);

  // Create dual faces corresponding to model vertices.
  {
    // Add dual faces for primal nodes attached to model faces.
    int pos = 0, node;
    while (int_unordered_set_next(model_face_nodes, &pos, &node))
    {
      // This rule does not apply to nodes on model edges.
      if (!int_unordered_set_contains(model_edge_nodes, node))
      {
        // Traverse the model faces attached to this node and hook up their 
        // corresponding dual vertices to a new dual face.
        int_unordered_set_t* boundary_faces_for_node = primal_boundary_faces_for_node[node];
        ASSERT(boundary_faces_for_node != NULL);
        int num_dual_nodes = boundary_faces_for_node->size;
        point_t dual_nodes[num_dual_nodes];
        int pos1 = 0, bface, i = 0;
        while (int_unordered_set_next(boundary_faces_for_node, &pos1, &bface))
        {
          // Retrieve the dual node index for this boundary face.
          int* dual_node_p = int_int_unordered_map_get(dual_node_for_model_face, bface);
          ASSERT(dual_node_p != NULL);
          dual_nodes[i] = dual_mesh->nodes[*dual_node_p];
          ++i;
        }

        // Order the dual nodes by constructing a polygonal face.
        polygon_t* dual_polygon = polygon_giftwrap(dual_nodes, num_dual_nodes);
        int_array_t* face_nodes = int_array_new();
        int_array_resize(face_nodes, num_dual_nodes);
        memcpy(face_nodes->data, polygon_ordering(dual_polygon), sizeof(int)*num_dual_nodes);
        nodes_for_dual_face[df_offset] = face_nodes;
        dual_polygon = NULL;
        ++df_offset;
      }
    }

    // Add dual faces for primal nodes attached to model edges.
    // This can be gross, since some edges may be non-manifold.
    int edge;
    pos = 0;
    while (int_unordered_set_next(model_edges, &pos, &edge))
    { 
      // Traverse the boundary faces attached to this edge.
      int_unordered_set_t* faces_for_edge = primal_faces_for_edge[edge];
      int pos1 = 0, face;
      while (int_unordered_set_next(faces_for_edge, &pos1, &face))
      {
        if (int_unordered_set_contains(external_model_faces, face) || 
            int_unordered_set_contains(internal_model_faces, face))
        {
          // FIXME
        }
      }
    }

    // Add dual faces for primal nodes which are model vertices.
    pos = 0;
    while (int_unordered_set_next(model_vertices, &pos, &node))
    { 
      // Traverse the boundary faces attached to this node.
      int_unordered_set_t* boundary_faces_for_node = primal_boundary_faces_for_node[node];
      int pos1 = 0, face;
      while (int_unordered_set_next(boundary_faces_for_node, &pos1, &face))
      {
        // FIXME
      }
    }
  }

  // Create dual cells.
  int dc_offset = 0;
  int_array_t** faces_for_dual_cell = polymec_malloc(sizeof(int_array_t*) * num_dual_cells);
  memset(faces_for_dual_cell, 0, sizeof(int_array_t*) * num_dual_cells);
  // FIXME
  ASSERT(dc_offset == num_dual_cells);

  // Allocate mesh connectivity storage and move all the data into place.
  mesh_reserve_connectivity_storage(dual_mesh);
  for (int c = 0; c < num_dual_cells; ++c)
  {
    int_array_t* cell_faces = faces_for_dual_cell[c];
    memcpy(&dual_mesh->cell_faces[dual_mesh->cell_face_offsets[c]], cell_faces->data, sizeof(int)*cell_faces->size);
    for (int f = 0; f < cell_faces->size; ++f)
    {
      int face = cell_faces->data[f];
      if (dual_mesh->face_cells[2*face] == -1)
        dual_mesh->face_cells[2*face] = c;
      else
        dual_mesh->face_cells[2*face+1] = c;
    }
  }
  for (int f = 0; f < num_dual_faces; ++f)
  {
    int_array_t* face_nodes = nodes_for_dual_face[f];
    memcpy(&dual_mesh->face_nodes[dual_mesh->face_node_offsets[f]], face_nodes->data, sizeof(int)*face_nodes->size);
  }

  // Clean up.
  for (int c = 0; c < num_dual_cells; ++c)
    int_array_free(faces_for_dual_cell[c]);
  polymec_free(faces_for_dual_cell);
  for (int f = 0; f < num_dual_faces; ++f)
    int_array_free(nodes_for_dual_face[f]);
  polymec_free(nodes_for_dual_face);
  for (int e = 0; e < tet_mesh->num_edges; ++e)
  {
    int_unordered_set_free(primal_cells_for_edge[e]);
    int_unordered_set_free(primal_faces_for_edge[e]);
  }
  polymec_free(primal_cells_for_edge);
  polymec_free(primal_faces_for_edge);
  for (int n = 0; n < tet_mesh->num_nodes; ++n)
  {
    if (primal_boundary_faces_for_node[n] != NULL)
      int_unordered_set_free(primal_boundary_faces_for_node[n]);
  }
  polymec_free(primal_boundary_faces_for_node);
  int_int_unordered_map_free(dual_node_for_edge);
  int_int_unordered_map_free(dual_node_for_model_face);
  int_unordered_set_free(model_vertices);
  int_unordered_set_free(model_edges);
  int_unordered_set_free(model_edge_nodes);
  int_unordered_set_free(external_boundary_tets);
  int_unordered_set_free(external_model_faces);
  int_unordered_set_free(external_model_face_edges);
  int_unordered_set_free(model_face_nodes);
  int_unordered_set_free(internal_boundary_tets);
  int_unordered_set_free(internal_model_faces);
  int_unordered_set_free(internal_model_face_edges);

  // Compute mesh geometry.
  mesh_compute_geometry(dual_mesh);

  return dual_mesh;
}
Example #6
0
int main(int argc, char *argv[])
{
  lob_t id, options, json;
  mesh_t mesh;
  net_udp4_t udp4;
  net_tcp4_t tcp4;
  int port = 0;

  if(argc==2)
  {
    port = atoi(argv[1]);
  }

  id = util_fjson("id.json");
  if(!id) return -1;
  
  mesh = mesh_new(0);
  mesh_load(mesh,lob_get_json(id,"secrets"),lob_get_json(id,"keys"));
  mesh_on_discover(mesh,"auto",mesh_add); // auto-link anyone
  mesh_on_open(mesh,"path",path_on_open); // add path support

  options = lob_new();
  lob_set_int(options,"port",port);

  udp4 = net_udp4_new(mesh, options);
  util_sock_timeout(udp4->server,100);

  tcp4 = net_tcp4_new(mesh, options);

  json = mesh_json(mesh);
  printf("%s\n",lob_json(json));
  printf("%s\n",mesh_uri(mesh, NULL));

  while(net_udp4_receive(udp4) && net_tcp4_loop(tcp4));

  /*
  if(util_loadjson(s) != 0 || (sock = util_server(0,1000)) <= 0)
  {
    printf("failed to startup %s or %s\n", strerror(errno), crypt_err());
    return -1;
  }

  printf("loaded hashname %s\n",s->id->hexname);

  // create/send a ping packet  
  c = chan_new(s, bucket_get(s->seeds, 0), "link", 0);
  p = chan_packet(c);
  chan_send(c, p);
  util_sendall(s,sock);

  in = path_new("ipv4");
  while(util_readone(s, sock, in) == 0)
  {
    switch_loop(s);

    while((c = switch_pop(s)))
    {
      printf("channel active %d %s %s\n",c->ended,c->hexid,c->to->hexname);
      if(util_cmp(c->type,"connect") == 0) ext_connect(c);
      if(util_cmp(c->type,"link") == 0) ext_link(c);
      if(util_cmp(c->type,"path") == 0) ext_path(c);
      while((p = chan_pop(c)))
      {
        printf("unhandled channel packet %.*s\n", p->json_len, p->json);      
        lob_free(p);
      }
    }

    util_sendall(s,sock);
  }
  */
  perror("exiting");
  return 0;
}
Example #7
0
Mesh * mesh_triangulate_polygon( const Polygon *poly )
{
    g_return_val_if_fail( poly != NULL, NULL );
    g_return_val_if_fail( poly->vertices != NULL, NULL );
    g_return_val_if_fail( g_list_length( poly->vertices ) >= 3, NULL );

    reflex_vertices = g_hash_table_new( NULL, NULL );
    convex_vertices = g_hash_table_new( NULL, NULL );
    ears = g_hash_table_new( NULL, NULL );

    /* create a new mesh */
    Mesh *mesh = mesh_new();
    /* add polygon's nodes and edges to the mesh */
    add_polygon_to_mesh( mesh, poly );

    /* take the first half-edge of the first edge as the starting half-edge */
    HalfEdge *he_start = &EDGE(mesh->edges->data)->he[0];
    HalfEdge *he_iter = he_start;
    /* iterate over half-edges lying on the inner side of the boundary */
    do
    {
        /* classify half-edge's origin according to its convexity */
        if ( halfedge_origin_is_convex( he_iter ) )
            g_hash_table_insert( convex_vertices, he_iter->origin, he_iter );
        else
            g_hash_table_insert( reflex_vertices, he_iter->origin, he_iter );

        he_iter = he_iter->next;
    }
    while ( he_iter != he_start );

    /* iterate over convex vertices */
    GHashTableIter convex_vert_iter;
    g_hash_table_iter_init( &convex_vert_iter, convex_vertices );
    gpointer key, value;
    while ( g_hash_table_iter_next( &convex_vert_iter, &key, &value ) )
    {
        HalfEdge *conv_he = HALFEDGE(value);
        /* check if the convex vertex is an ear */
        if ( halfedge_origin_is_ear( conv_he ) )
            g_hash_table_insert( ears, conv_he->origin, conv_he );
    }

    /* iterate over ears */
    GHashTableIter ears_iter;
    g_hash_table_iter_init( &ears_iter, ears );
    while ( g_hash_table_iter_next( &ears_iter, &key, &value) )
    {
        /* since we will cut it off, remove the ear from ears and convex vertex
         * hash table */
        g_hash_table_remove( ears, key );
        g_hash_table_remove( convex_vertices, key );

        HalfEdge *he2 = HALFEDGE(value);
        HalfEdge *he1 = he2->previous;
        Node *n1 = he1->origin;
        Node *n3 = he2->pair->origin;

        /* cut off the ear: */
        /* add an edge connecting the ear's neighbours */
        Edge *e = mesh_add_edge( mesh, n3, n1 );
        HalfEdge *he3 = &e->he[0];
        /* add ear's triangle to the mesh */
        mesh_add_element( mesh, he1, he2, he3 );

        he1 = &e->he[1];
        he2 = he1->next;

        gboolean was_reflex_1 = FALSE;
        gboolean was_reflex_became_convex_1 = FALSE;
        gboolean was_reflex_2 = FALSE;
        gboolean was_reflex_became_convex_2 = FALSE;

        /* update the status of the ear's neighbours */

        /* first, we need to update the reflex status of both neighbours, as
         * we need up-to-date info about reflex vertices in the "ear-ness" test */
        if ( g_hash_table_lookup( reflex_vertices, n1 ) )
        {
            was_reflex_1 = TRUE;
            /* reflex vertex can become convex */
            if ( halfedge_origin_is_convex( he1 ) )
            {
                was_reflex_became_convex_1 = TRUE;
                /* is now convex, remove from reflex vertices */
                g_hash_table_remove( reflex_vertices, n1 );
            }
        }

        if ( g_hash_table_lookup( reflex_vertices, n3 ) )
        {
            was_reflex_2 = TRUE;
            if ( halfedge_origin_is_convex( he2 ) )
            {
                was_reflex_became_convex_2 = TRUE;
                g_hash_table_remove( reflex_vertices, n3 );
            }
        }

        /* now we can proceed with the other tests */
        if ( was_reflex_1 )
        {
            if ( was_reflex_became_convex_1 )
            {
                /* add to convex vertices */
                g_hash_table_insert( convex_vertices, n1, he1 );
                /* if was reflex and became convex and even an ear, add it to
                 * ears */
                if ( halfedge_origin_is_ear( he1 ) )
                    g_hash_table_insert( ears, n1, he1 );
            }
            else
                /* if it stayed reflex, just update it with a new half-edge */
                g_hash_table_insert( reflex_vertices, n1, he1 );
        }
        else if ( g_hash_table_lookup( ears, n1 ) )
        {
            /* if it was an ear and now is not, remove it from ears (but it
             * stays convex) */
            if ( ! halfedge_origin_is_ear( he1 ) )
                g_hash_table_remove( ears, n1 );
            else
                /* if it stayed an ear, just update it with a new half-edge */
                g_hash_table_insert( ears, n1, he1 );
        }
        else if ( g_hash_table_lookup( convex_vertices, n1 ) )
        {
            /* if it was convex and now became an ear, insert it into ears */
            if ( halfedge_origin_is_ear( he1 ) )
                g_hash_table_insert( ears, n1, he1 );
            else
                /* otherwise just update it with a new half-edge */
                g_hash_table_insert( convex_vertices, n1, he1 );
        }

        /* the same process with the other neighbour */
        if ( was_reflex_2 )
        {
            if ( was_reflex_became_convex_2 )
            {
                g_hash_table_insert( convex_vertices, n3, he2 );
                if ( halfedge_origin_is_ear( he2 ) )
                    g_hash_table_insert( ears, n3, he2 );
            }
        }
        else if ( g_hash_table_lookup( ears, n3 ) )
        {
            if ( ! halfedge_origin_is_ear( he2 ) )
                g_hash_table_remove( ears, n3 );
        }
        else if ( g_hash_table_lookup( convex_vertices, n3 ) )
        {
            if ( halfedge_origin_is_ear( he2 ) )
                g_hash_table_insert( ears, n3, he2 );
        }
        
        /* we changed the ears, so update the iterator */
        g_hash_table_iter_init( &ears_iter, ears );

        he3 = he2->next;
        /* check if there are only three edges left */
        if ( he3->next == he1 )
        {
            /* if there are, so just add this last element and break out from
             * the loop */
            mesh_add_element( mesh, he1, he2, he3 );
            break;
        }
    }

    /* clean up */
    g_hash_table_destroy( reflex_vertices );
    g_hash_table_destroy( convex_vertices );
    g_hash_table_destroy( ears );

    /* return the resulting mesh */
    return mesh;
}
Example #8
0
mesh_t* create_pebi_mesh(MPI_Comm comm, 
                         point_t* cell_centers, real_t* cell_volumes, int num_cells,
                         int* faces, real_t* face_areas, point_t* face_centers, 
                         int num_faces)
{
  // Check input.
  ASSERT(cell_centers != NULL);
  ASSERT(cell_volumes != NULL);
  ASSERT(num_cells > 0);
  ASSERT(faces != NULL);
  ASSERT(face_areas != NULL);
  ASSERT(num_faces >= 0);
#ifndef NDEBUG
  for (int f = 0; f < num_faces; ++f)
  {
    ASSERT(faces[2*f] >= 0);
    ASSERT((faces[2*f+1] >= 0) || (faces[2*f+1] == -1));
  }
#endif

  mesh_t* mesh = mesh_new(comm, num_cells, 0, num_faces, 0);

  // Transcribe the mesh cell centers, which are the only connection to 
  // spatial geometry.
  memcpy(mesh->cell_centers, cell_centers, sizeof(point_t)*num_cells);

  // Copy over the face-cell connectivity directly.
  memcpy(mesh->face_cells, faces, 2*sizeof(int)*num_faces);

  // Copy over the face areas directly.
  memcpy(mesh->face_areas, face_areas, sizeof(real_t)*num_faces);

  // Go through the list of faces and count the faces attached to each cell,
  // storing the tally in the set of cell face offsets.
  for (int f = 0; f < num_faces; ++f)
  {
    mesh->cell_face_offsets[faces[2*f]] += 1;
    if (faces[2*f+1] != -1)
      mesh->cell_face_offsets[faces[2*f]] += 1;
  }
  // Convert these face offsets to compressed row storage format.
  for (int c = 1; c <= num_cells; ++c)
    mesh->cell_face_offsets[c] += mesh->cell_face_offsets[c-1];

  // Now fill the mesh's cell_faces array.
  int* cell_face_count = polymec_malloc(sizeof(int) * num_cells);
  memset(cell_face_count, 0, sizeof(int) * num_cells);
  mesh->cell_faces = polymec_realloc(mesh->cell_faces, sizeof(int) * mesh->cell_face_offsets[num_cells]);
  for (int f = 0; f < num_faces; ++f)
  {
    int c1 = faces[2*f];
    mesh->cell_faces[mesh->cell_face_offsets[c1] + cell_face_count[c1]] = f;
    ++cell_face_count[c1];
    int c2 = faces[2*f+1];
    if (c2 != -1)
    {
      mesh->cell_faces[mesh->cell_face_offsets[c2] + cell_face_count[c2]] = f;
      ++cell_face_count[c2];
    }
  }
  polymec_free(cell_face_count);

  // Set the cell volumes.
  memcpy(mesh->cell_volumes, cell_volumes, sizeof(real_t)*num_cells);

  // Set or compute face centers.
  // We compute information for interior faces first.
  for (int f = 0; f < num_faces; ++f)
  {
    point_t* xf = &mesh->face_centers[f];
    vector_t* nf = &mesh->face_normals[f];
    int c1 = mesh->face_cells[2*f];
    int c2 = mesh->face_cells[2*f];
    if (c2 != -1) // Interior face
    {
      point_t* xc1 = &mesh->cell_centers[c1];
      point_t* xc2 = &mesh->cell_centers[c2];
      if (face_centers == NULL)
      {
        // Assume each face center lies at the midpoint between its cells.
        xf->x = 0.5 * (xc1->x + xc2->x);
        xf->y = 0.5 * (xc1->y + xc2->y);
        xf->z = 0.5 * (xc1->z + xc2->z);
      }
      else
      {
        xf->x = face_centers[f].x;
        xf->y = face_centers[f].y;
        xf->z = face_centers[f].z;
      }

      // The face normal should connect xc1 and xc2.
      point_displacement(xc1, xc2, nf);
      vector_normalize(nf);
    }

    // Now use the existing information to compute information for 
    // boundary faces.
    for (int f = 0; f < num_faces; ++f)
    {
      int c1 = mesh->face_cells[2*f];
      int c2 = mesh->face_cells[2*f];
      if (c2 == -1)
      {
        // Estimate the cell-face distance by assuming an isotropic cell.
        real_t V = mesh->cell_volumes[c1];
        real_t d = pow(V, 1.0/3.0);

        // Form the normal vector for the face by assuming that all face 
        // normals sum to zero.
        vector_t* nf = &mesh->face_normals[f];
        nf->x = nf->y = nf->z = 0.0;
        for (int ff = mesh->cell_face_offsets[c1]; ff < mesh->cell_face_offsets[c1+1]; ++ff)
        {
          vector_t* nff = &mesh->face_normals[ff];
          nf->x -= nff->x;
          nf->y -= nff->y;
          nf->z -= nff->z;
        }

        // Compute the face center.
        if (face_centers == NULL)
        {
          point_t* xc = &mesh->cell_centers[c1];
          point_t* xf = &mesh->face_centers[f];
          xf->x = xc->x + d*nf->x;
          xf->y = xc->y + d*nf->y;
          xf->z = xc->z + d*nf->z;
        }
        else 
        {
          xf->x = face_centers[f].x;
          xf->y = face_centers[f].y;
          xf->z = face_centers[f].z;
        }
      }
    }
  }

  mesh_add_feature(mesh, PEBI);
  return mesh;
}
Example #9
0
mesh_t* mesh_from_fe_mesh(fe_mesh_t* fe_mesh)
{
  // Feel out the faces for the finite element mesh. Do we need to create 
  // them ourselves, or are they already all there?
  int num_cells = fe_mesh_num_elements(fe_mesh);
  int num_faces = fe_mesh_num_faces(fe_mesh);
  int* cell_face_offsets = polymec_malloc(sizeof(int) * (num_cells + 1));
  cell_face_offsets[0] = 0;
  int* cell_faces = NULL;
  int* face_node_offsets = NULL;
  int* face_nodes = NULL;
  if (num_faces == 0)
  {
    // Traverse the element blocks and figure out the number of faces per cell.
    int pos = 0, elem_offset = 0;
    char* block_name;
    fe_block_t* block;
    while (fe_mesh_next_block(fe_mesh, &pos, &block_name, &block))
    {
      int num_block_elem = fe_block_num_elements(block);
      fe_mesh_element_t elem_type = fe_block_element_type(block);
      int num_elem_faces = get_num_cell_faces(elem_type);
      for (int i = 0; i < num_block_elem; ++i)
        cell_face_offsets[elem_offset+i+1] = cell_face_offsets[elem_offset+i] + num_elem_faces;
      elem_offset += num_block_elem;
    }

    // Now assemble the faces for each cell.
    int_tuple_int_unordered_map_t* node_face_map = int_tuple_int_unordered_map_new();
    cell_faces = polymec_malloc(sizeof(int) * cell_face_offsets[num_cells]);

    // We build the face->node connectivity data on-the-fly.
    int_array_t* face_node_offsets_array = int_array_new();
    int_array_append(face_node_offsets_array, 0);
    int_array_t* face_nodes_array = int_array_new();

    pos = 0, elem_offset = 0;
    while (fe_mesh_next_block(fe_mesh, &pos, &block_name, &block))
    {
      int num_block_elem = fe_block_num_elements(block);
      fe_mesh_element_t elem_type = fe_block_element_type(block);
      int num_elem_nodes = fe_block_num_element_nodes(block, 0);
      int elem_nodes[num_elem_nodes];
      for (int i = 0; i < num_block_elem; ++i)
      {
        fe_block_get_element_nodes(block, i, elem_nodes);
        int offset = cell_face_offsets[elem_offset+i];
        get_cell_faces(elem_type, elem_nodes, node_face_map, 
                       &cell_faces[offset], face_node_offsets_array,
                       face_nodes_array);
      }
      elem_offset += num_block_elem;
    }

    // Record the total number of faces and discard the map.
    num_faces = node_face_map->size;
    int_tuple_int_unordered_map_free(node_face_map);

    // Gift the contents of the arrays to our pointers.
    face_node_offsets = face_node_offsets_array->data;
    int_array_release_data_and_free(face_node_offsets_array);
    face_nodes = face_nodes_array->data;
    int_array_release_data_and_free(face_nodes_array);
  }
  else
  {
    // Fill in these arrays block by block.
    int pos = 0;
    char* block_name;
    fe_block_t* block;
    int block_cell_offset = 0;
    while (fe_mesh_next_block(fe_mesh, &pos, &block_name, &block))
    {
      int num_block_elem = fe_block_num_elements(block);
      for (int i = 0; i < num_block_elem; ++i)
        cell_face_offsets[block_cell_offset+i] = cell_face_offsets[block_cell_offset+i-1] + block->elem_face_offsets[i];
      block_cell_offset += num_block_elem;
    }

    cell_faces = polymec_malloc(sizeof(int) * cell_face_offsets[num_cells]);
    pos = 0, block_cell_offset = 0;
    while (fe_mesh_next_block(fe_mesh, &pos, &block_name, &block))
    {
      int num_block_elem = fe_block_num_elements(block);
      memcpy(&cell_faces[cell_face_offsets[block_cell_offset]], block->elem_faces, sizeof(int) * block->elem_face_offsets[num_block_elem]);
      block_cell_offset += num_block_elem;
    }

    // We just borrow these from the mesh. Theeenks!
    face_node_offsets = fe_mesh->face_node_offsets;
    face_nodes = fe_mesh->face_nodes;
  }
  ASSERT(cell_faces != NULL);
  ASSERT(face_node_offsets != NULL);
  ASSERT(face_nodes != NULL);

  // Create the finite volume mesh and set up its cell->face and face->node 
  // connectivity.
  int num_ghost_cells = 0; // FIXME!
  mesh_t* mesh = mesh_new(fe_mesh_comm(fe_mesh), 
                          num_cells, num_ghost_cells, 
                          num_faces,
                          fe_mesh_num_nodes(fe_mesh));
  memcpy(mesh->cell_face_offsets, cell_face_offsets, sizeof(int) * (mesh->num_cells+1));
  memcpy(mesh->face_node_offsets, face_node_offsets, sizeof(int) * (mesh->num_faces+1));
  mesh_reserve_connectivity_storage(mesh);
  memcpy(mesh->cell_faces, cell_faces, sizeof(int) * (mesh->cell_face_offsets[mesh->num_cells]));
  memcpy(mesh->face_nodes, face_nodes, sizeof(int) * (mesh->face_node_offsets[mesh->num_faces]));

  // Set up face->cell connectivity.
  for (int c = 0; c < mesh->num_cells; ++c)
  {
    for (int f = mesh->cell_face_offsets[c]; f < mesh->cell_face_offsets[c+1]; ++f)
    {
      int face = mesh->cell_faces[f];
      if (mesh->face_cells[2*face] == -1)
        mesh->face_cells[2*face] = c;
      else
        mesh->face_cells[2*face+1] = c;
    }
  }

  // Set up face->edge connectivity and edge->node connectivity (if provided).
  if (fe_mesh->face_edges != NULL)
  {
    memcpy(mesh->face_edge_offsets, fe_mesh->face_edge_offsets, sizeof(int) * (mesh->num_faces+1));
    mesh->face_edges = polymec_malloc(sizeof(int) * fe_mesh->face_edge_offsets[mesh->num_faces]);
    memcpy(mesh->face_edges, fe_mesh->face_edges, sizeof(int) * fe_mesh->face_edge_offsets[mesh->num_faces]);
  }
  else
  {
    // Construct edges if we didn't find them.
    mesh_construct_edges(mesh);
  }

  // Copy the node positions into place.
  memcpy(mesh->nodes, fe_mesh_node_positions(fe_mesh), sizeof(point_t) * mesh->num_nodes);

  // Calculate geometry.
  mesh_compute_geometry(mesh);

  // Sets -> tags.
  int pos = 0, *set;
  size_t set_size;
  char* set_name;
  while (fe_mesh_next_element_set(fe_mesh, &pos, &set_name, &set, &set_size))
  {
    int* tag = mesh_create_tag(mesh->cell_tags, set_name, set_size);
    memcpy(tag, set, sizeof(int) * set_size);
  }
  pos = 0;
  while (fe_mesh_next_face_set(fe_mesh, &pos, &set_name, &set, &set_size))
  {
    int* tag = mesh_create_tag(mesh->face_tags, set_name, set_size);
    memcpy(tag, set, sizeof(int) * set_size);
  }
  pos = 0;
  while (fe_mesh_next_edge_set(fe_mesh, &pos, &set_name, &set, &set_size))
  {
    int* tag = mesh_create_tag(mesh->edge_tags, set_name, set_size);
    memcpy(tag, set, sizeof(int) * set_size);
  }
  pos = 0;
  while (fe_mesh_next_node_set(fe_mesh, &pos, &set_name, &set, &set_size))
  {
    int* tag = mesh_create_tag(mesh->node_tags, set_name, set_size);
    memcpy(tag, set, sizeof(int) * set_size);
  }

  // Clean up.
  polymec_free(cell_face_offsets);
  polymec_free(cell_faces);
  if (fe_mesh_num_faces(fe_mesh) == 0)
  {
    polymec_free(face_node_offsets);
    polymec_free(face_nodes);
  }

  return mesh;
}
Example #10
0
void test_matrix()
{
	struct MeshConfig *conf;
	struct MD *x[2], *x0[2];
	int i;
	double c[2];
	double z0;

	FILE *fplot;

	conf = mesh_new(
		2.4e-3, 10e-3,
		0,
		3e-3,
		0.79e-3,
		2.2
		);

	z0 = mom(conf, x0, x, c);


	printf("C0 = %le F        C1 = %le F\n", c[0], c[1]);
	printf("Z0 = %lf Ohm\n", z0);

	fplot = fopen("dielectric.plot", "w");

	if (fplot) {
		fprintf(fplot, "#!"PATH_GNUPLOT"\n");
		fprintf(fplot, "# top all charges\n");
		fprintf(fplot, "plot '-' notitle with impulse, \\\n"
				"\t'-' notitle with impulse\n");

		for (i = conf->index[ID_STRIP0_START];
			i < conf->index[ID_STRIP0_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[1]->buf[i]);
		}

		for (i = conf->index[ID_DIELECTRIC0_START];
			i < conf->index[ID_DIELECTRIC0_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[1]->buf[i]);
		}
		fprintf(fplot, "e\n");

		fprintf(fplot, "# bottom all charges\n");

		for (i = conf->index[ID_STRIP1_START];
			i < conf->index[ID_STRIP1_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[1]->buf[i]);
		}

		for (i = conf->index[ID_DIELECTRIC1_START];
			i < conf->index[ID_DIELECTRIC1_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[1]->buf[i]);
		}
		fprintf(fplot, "e\npause -1\n");
		/*****/
		fprintf(fplot, "# top free charges\n");
		fprintf(fplot, "plot '-' notitle with impulse, \\\n"
				"\t'-' notitle with impulse\n");

		for (i = conf->index[ID_STRIP0_START];
			i < conf->index[ID_STRIP0_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[0]->buf[i]);
		}

		for (i = conf->index[ID_DIELECTRIC0_START];
			i < conf->index[ID_DIELECTRIC0_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[0]->buf[i]);
		}
		fprintf(fplot, "e\n");

		fprintf(fplot, "# bottom free charges\n");

		for (i = conf->index[ID_STRIP1_START];
			i < conf->index[ID_STRIP1_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[0]->buf[i]);
		}

		for (i = conf->index[ID_DIELECTRIC1_START];
			i < conf->index[ID_DIELECTRIC1_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[0]->buf[i]);
		}
		fprintf(fplot, "e\npause -1\n");
		fclose(fplot);
	}

	fplot = fopen("freespace.plot", "w");

	if (fplot) {
		fprintf(fplot, "#!"PATH_GNUPLOT"\n");
		fprintf(fplot, "# top free charges\n");
		fprintf(fplot, "plot '-' notitle with impulse, \\\n"
				"\t'-' notitle with impulse\n");

		for (i = conf->index[ID_STRIP0_START];
			i < conf->index[ID_STRIP0_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[1]->buf[i]);
		}

		fprintf(fplot, "e\n");

		fprintf(fplot, "# bottom free charges\n");

		for (i = conf->index[ID_STRIP1_START];
			i < conf->index[ID_STRIP1_END]; ++i) {
			fprintf(fplot, "%le %le\n", conf->mesh[i].centre, x[1]->buf[i]);
		}

		fprintf(fplot, "e\npause -1\n");
		fclose(fplot);
	}
	md_free(x[0]);
	md_free(x[1]);

	mesh_free(conf);
}
Example #11
0
// resolves collisions between bodies, returning new body count
int collide(int n, body bodies[]) {
  // initialize disjoint set and bodies to include
  set* bsets[n];
  int include[n];
  for (int i = 0; i < n; i++) {
    bsets[i] = make_set(i);
    include[i] = 1;
  }

  // find largest object
  double maxrad = RADIUS(bodies[0].m);
  for (int i = 0; i < n; i++) {
    double rad = RADIUS(bodies[i].m);
    if (rad > maxrad)
      maxrad = rad;
  }

  // form mesh for collision detection
  mesh* m = mesh_new(maxrad * 2);
  for (int i = 0; i < n; i++)
    mesh_put(m, bodies[i].pos, i);

  // find collisions
  for (int i = 0; i < n; i++) {
    vector ipos = bodies[i].pos;
    double irad = RADIUS(bodies[i].m);

    // which bodies are in contact with this one?
    // look up position in mesh
    body_list* next = mesh_get(m, ipos, 1);
    for (body_list* cur = next; cur; cur = next) {
      // get candidate collider
      int j = cur->index;
      vector jpos = bodies[j].pos;
      double jrad = RADIUS(bodies[j].m);

      // merge sets of colliding objects
      if (dist(ipos, jpos) < (irad + jrad) * (irad + jrad))
        merge(bsets[i], bsets[j]);

      // traverse and free
      next = cur->next;
      free(cur);
    }
  }

  // free the mesh
  mesh_free(m);

  // merge objects
  for (int i = 0; i < n; i++) {
    int rootidx = get_value(find(bsets[i]));
    if (rootidx != i) {
      include[i] = 0;
      bodies[rootidx] = body_merge(bodies[rootidx], bodies[i]);
    }
  }

  // free sets
  for (int i = 0; i < n; i++)
    free(bsets[i]);

  // copy down
  int j = 0;
  for (int i = 0; i < n; i++) {
    if (include[i])
      bodies[j++] = bodies[i];
  }

  return j;
}
Example #12
0
mesh_t* crop_mesh(mesh_t* mesh, sp_func_t* boundary_func, mesh_crop_t crop_type)
{
  // Mark the cells whose centers fall outside the boundary.
  int_unordered_set_t* outside_cells = int_unordered_set_new();
  for (int cell = 0; cell < mesh->num_cells; ++cell)
  {
    real_t dist;
    sp_func_eval(boundary_func, &mesh->cell_centers[cell], &dist);
    if (dist > 0.0)
      int_unordered_set_insert(outside_cells, cell);
  }

  // Count up the remaining faces and nodes, and make a list of boundary faces.
  int_unordered_set_t* remaining_ghosts = int_unordered_set_new();
  int_unordered_set_t* boundary_faces = int_unordered_set_new();
  int_int_unordered_map_t* remaining_nodes = int_int_unordered_map_new();
  int_int_unordered_map_t* remaining_faces = int_int_unordered_map_new();
  int new_face_index = 0, new_node_index = 0;
  for (int cell = 0; cell < mesh->num_cells; ++cell)
  {
    if (int_unordered_set_contains(outside_cells, cell)) continue;

    int pos = 0, face;
    while (mesh_cell_next_face(mesh, cell, &pos, &face))
    {
      // This face is still in the mesh.
      if (!int_int_unordered_map_contains(remaining_faces, face))
        int_int_unordered_map_insert(remaining_faces, face, new_face_index++);

      // A boundary face is a face with only one cell attached to it.
      int opp_cell = mesh_face_opp_cell(mesh, face, cell);
      if ((opp_cell == -1) || int_unordered_set_contains(outside_cells, opp_cell))
        int_unordered_set_insert(boundary_faces, face);
      else if (opp_cell >= mesh->num_cells)
        int_unordered_set_insert(remaining_ghosts, opp_cell);
      int pos1 = 0, node;
      while (mesh_face_next_node(mesh, face, &pos1, &node))
      {
        if (!int_int_unordered_map_contains(remaining_nodes, node))
          int_int_unordered_map_insert(remaining_nodes, node, new_node_index++);
      }
    }
  }

  // Convert the face and node maps to arrays.
  int* face_map = polymec_malloc(sizeof(int) * mesh->num_faces);
  for (int i = 0; i < mesh->num_faces; ++i)
    face_map[i] = -1;
  {
    int pos = 0, old_face, new_face;
    while (int_int_unordered_map_next(remaining_faces, &pos, &old_face, &new_face))
      face_map[old_face] = new_face;
  }
  int* node_map = polymec_malloc(sizeof(int) * mesh->num_nodes);
  for (int i = 0; i < mesh->num_nodes; ++i)
    node_map[i] = -1;
  {
    int pos = 0, old_node, new_node;
    while (int_int_unordered_map_next(remaining_nodes, &pos, &old_node, &new_node))
      node_map[old_node] = new_node;
  }

  // Do a partial clean up.
  int num_new_faces = remaining_faces->size;
  int num_new_nodes = remaining_nodes->size;
  int num_new_ghosts = remaining_ghosts->size;
  int_int_unordered_map_free(remaining_nodes);
  int_int_unordered_map_free(remaining_faces);
  int_unordered_set_free(remaining_ghosts);

  // Make a new mesh.
  mesh_t* cropped_mesh = mesh_new(mesh->comm, 
                                  mesh->num_cells - outside_cells->size,
                                  num_new_ghosts, num_new_faces, num_new_nodes);

  // Reserve storage.
  int new_cell = 0;
  cropped_mesh->cell_face_offsets[0] = 0;
  for (int cell = 0; cell < mesh->num_cells; ++cell)
  {
    if (int_unordered_set_contains(outside_cells, cell)) continue;
    int num_cell_faces = mesh_cell_num_faces(mesh, cell);
    cropped_mesh->cell_face_offsets[new_cell+1] = cropped_mesh->cell_face_offsets[new_cell] + num_cell_faces;
    ++new_cell;
  }
  cropped_mesh->face_node_offsets[0] = 0;
  for (int f = 0; f < mesh->num_faces; ++f)
  {
    int new_face = face_map[f];
    if (new_face != -1)
    {
      int num_face_nodes = mesh_face_num_nodes(mesh, f);
      cropped_mesh->face_node_offsets[new_face+1] = num_face_nodes;
    }
  }
  for (int f = 0; f < cropped_mesh->num_faces; ++f)
    cropped_mesh->face_node_offsets[f+1] += cropped_mesh->face_node_offsets[f];
  mesh_reserve_connectivity_storage(cropped_mesh);

  // Hook up the faces and cells.
  new_cell = 0;
  for (int cell = 0; cell < mesh->num_cells; ++cell)
  {
    if (int_unordered_set_contains(outside_cells, cell)) continue;
    int num_cell_faces = mesh_cell_num_faces(mesh, cell);
    for (int f = 0; f < num_cell_faces; ++f)
    {
      int old_face = mesh->cell_faces[mesh->cell_face_offsets[cell]+f];
      int pos_old_face = (old_face >= 0) ? old_face : ~old_face;
      int new_face = face_map[pos_old_face];
      if (cropped_mesh->face_cells[2*new_face] == -1)
        cropped_mesh->face_cells[2*new_face] = new_cell;
      else
        cropped_mesh->face_cells[2*new_face+1] = new_cell;
      if (old_face < 0) new_face = ~new_face;
      cropped_mesh->cell_faces[cropped_mesh->cell_face_offsets[new_cell]+f] = new_face;
    }
    ++new_cell;
  }
  ASSERT(new_cell == cropped_mesh->num_cells);

  // Hook up faces and nodes.
  for (int f = 0; f < mesh->num_faces; ++f)
  {
    int new_face = face_map[f];
    if (new_face != -1)
    {
      int num_face_nodes = mesh_face_num_nodes(mesh, f);
      for (int n = 0; n < num_face_nodes; ++n)
      {
        int old_node = mesh->face_nodes[mesh->face_node_offsets[f]+n];
        int new_node = node_map[old_node];
        cropped_mesh->face_nodes[cropped_mesh->face_node_offsets[new_face]+n] = new_node;
      }
    }
  }

  // Copy node positions.
  for (int n = 0; n < mesh->num_nodes; ++n)
  {
    if (node_map[n] != -1)
      cropped_mesh->nodes[node_map[n]] = mesh->nodes[n];
  }

  // Construct edges.
  mesh_construct_edges(cropped_mesh);
  
  // Create the boundary faces tag.
  int* bf_tag = mesh_create_tag(cropped_mesh->face_tags, sp_func_name(boundary_func), boundary_faces->size);
  int pos = 0, i = 0, face;
  while (int_unordered_set_next(boundary_faces, &pos, &face))
    bf_tag[i++] = face_map[face];

  // Create a new exchanger from the old one.
  {
    exchanger_t* old_ex = mesh_exchanger(mesh);
    exchanger_t* new_ex = mesh_exchanger(cropped_mesh);
    int pos = 0, remote, *indices, num_indices;
    while (exchanger_next_send(old_ex, &pos, &remote, &indices, &num_indices))
    {
      int send_indices[num_indices], j = 0;
      for (int i = 0; i < num_indices; ++i)
        if (!int_unordered_set_contains(outside_cells, indices[i]))
          send_indices[j++] = indices[i];
      exchanger_set_send(new_ex, remote, send_indices, j, true);
    }
    pos = 0;
    while (exchanger_next_receive(old_ex, &pos, &remote, &indices, &num_indices))
    {
      int recv_indices[num_indices], j = 0;
      for (int i = 0; i < num_indices; ++i)
        if (!int_unordered_set_contains(outside_cells, indices[i]))
          recv_indices[j++] = indices[i];
      exchanger_set_receive(new_ex, remote, recv_indices, j, true);
    }
  }

  // Clean up.
  polymec_free(node_map);
  polymec_free(face_map);
  int_unordered_set_free(boundary_faces);
  int_unordered_set_free(outside_cells);

  // Now it remains just to project node positions.
  if (crop_type == PROJECT_NODES)
    project_nodes(cropped_mesh, boundary_func);
  else if (crop_type == PROJECT_FACES)
    project_faces(cropped_mesh, boundary_func);

  // Finally, compute the mesh geometry.
  mesh_compute_geometry(cropped_mesh);

  return cropped_mesh;
}