Ejemplo n.º 1
0
neighbor_pairing_t* create_simple_pairing(point_cloud_t* cloud, real_t h)
{
  point_weight_function_t* W = hat_function_new(h);

  // Toss all the points into a kd-tree.
  kd_tree_t* tree = kd_tree_new(cloud->points, cloud->num_points);

  // Now do a neighbor search -- everything that falls within h of a point 
  // is a neighbor.
  int_array_t* pairs = int_array_new();
  real_array_t* weights = real_array_new();
  for (int i = 0; i < cloud->num_points; ++i)
  {
    point_t* xi = &cloud->points[i];
    int_array_t* neighbors = kd_tree_within_radius(tree, &cloud->points[i], h);
    for (int j = 0; j < neighbors->size; ++j)
    {
      int k = neighbors->data[j];
      if (k > i)
      {
        int_array_append(pairs, i);
        int_array_append(pairs, k);
        point_t* xk = &cloud->points[k];
        vector_t y;
        point_displacement(xk, xi, &y);
        real_array_append(weights, point_weight_function_value(W, &y));
      }
    }
    int_array_free(neighbors);
  }
  kd_tree_free(tree);
  point_weight_function_free(W);

  exchanger_t* ex = exchanger_new(MPI_COMM_SELF);
  neighbor_pairing_t* pairing = neighbor_pairing_new("simple pairing", 
                                                     pairs->size/2,
                                                     pairs->data,
                                                     weights->data,
                                                     ex);
  int_array_release_data_and_free(pairs);
  real_array_release_data_and_free(weights);
  return pairing;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
neighbor_pairing_t* distance_based_neighbor_pairing_new(point_cloud_t* points,
                                                        real_t* R,
                                                        int* num_ghost_points)
{
  ASSERT(R != NULL);
  ASSERT(num_ghost_points != NULL);
#ifndef NDEBUG
  for (int i = 0; i < points->num_points; ++i)
    ASSERT(R[i] > 0.0);
#endif

  // Stick all the points into a kd-tree so that we can pair them up.
  kd_tree_t* tree = kd_tree_new(points->points, points->num_points);

  // Find the maximum radius of interaction.
  real_t R_max = -FLT_MAX;
  for (int i = 0; i < points->num_points; ++i)
    R_max = MAX(R_max, R[i]);

  // Add ghost points to the kd-tree and fetch an exchanger. This may add 
  // too many ghost points, but hopefully that won't be an issue.
  exchanger_t* ex = kd_tree_find_ghost_points(tree, points->comm, R_max);

  // We'll toss neighbor pairs into this expandable array.
  int_array_t* pair_array = int_array_new();

  for (int i = 0; i < points->num_points; ++i)
  {
    // Find all the neighbors for this point. We only count those 
    // neighbors {j} for which j > i.
    point_t* xi = &points->points[i];
    int_array_t* neighbors = kd_tree_within_radius(tree, xi, R_max);
    for (int k = 0; k < neighbors->size; ++k)
    {
      int j = neighbors->data[k];
      if (j > i)
      {
        real_t D = point_distance(xi, &points->points[j]);
        if (D < MAX(R[i], R[j]))
        {
          int_array_append(pair_array, i);
          int_array_append(pair_array, j);
        }
      }
    }
    int_array_free(neighbors);
  }

  // Create a neighbor pairing.
  int num_pairs = pair_array->size/2;
  neighbor_pairing_t* neighbors = 
    unweighted_neighbor_pairing_new("Distance-based point pairs", 
                                    num_pairs, pair_array->data, ex);

  // Set the number of ghost points referred to within the neighbor pairing.
  *num_ghost_points = kd_tree_size(tree) - points->num_points;

  // Clean up.
  int_array_release_data_and_free(pair_array); // Release control of data.
  kd_tree_free(tree);

  return neighbors;
}