Пример #1
0
static void mls_set_neighborhood(void* context, int i)
{
  mls_t* mls = context;

  // Extract the points.
  mls->N = stencil_size(mls->neighborhoods, i);
  int pos = 0, j, k = 0;
  while (stencil_next(mls->neighborhoods, i, &pos, &j, NULL))
  {
    mls->xj[k] = mls->domain->points[j];
    mls->hj[k] = mls->smoothing_lengths[j];
    ++k;
  }

  // Compute the basis vectors for the points in the neighborhood.
  int dim = mls->basis_dim;
  mls->basis = polymec_realloc(mls->basis, sizeof(real_t) * dim * mls->N);
  mls->basis_ddx = polymec_realloc(mls->basis_ddx, sizeof(real_t) * dim * mls->N);
  mls->basis_ddy = polymec_realloc(mls->basis_ddy, sizeof(real_t) * dim * mls->N);
  mls->basis_ddz = polymec_realloc(mls->basis_ddz, sizeof(real_t) * dim * mls->N);
  for (int n = 0; n < mls->N; ++n)
  {
    polynomial_compute_basis(mls->poly_degree, 0, 0, 0, &mls->xj[n], &mls->basis[dim*n]);
    polynomial_compute_basis(mls->poly_degree, 1, 0, 0, &mls->xj[n], &mls->basis_ddx[dim*n]);
    polynomial_compute_basis(mls->poly_degree, 0, 1, 0, &mls->xj[n], &mls->basis_ddy[dim*n]);
    polynomial_compute_basis(mls->poly_degree, 0, 0, 1, &mls->xj[n], &mls->basis_ddz[dim*n]);
  }
}
Пример #2
0
void polygon_clip(polygon_t* poly, polygon_t* other)
{
  // Do the clipping in 2D.
  point2_t pts[poly->num_vertices];
  for (int i = 0; i < poly->num_vertices; ++i)
  {
    int I = poly->ordering[i];
    plane_project(poly->plane, &poly->vertices[I], &pts[I]);
  }
  polygon2_t* poly2 = polygon2_new(pts, poly->num_vertices);

  point2_t other_pts[other->num_vertices];
  for (int i = 0; i < other->num_vertices; ++i)
  {
    int I = poly->ordering[i];
    plane_project(other->plane, &other->vertices[I], &other_pts[I]);
  }
  polygon2_t* other2 = polygon2_new(other_pts, other->num_vertices);

  polygon2_clip(poly2, other2);

  // Now re-embed the vertices.
  int num_vertices = polygon2_num_vertices(poly2);
  if (poly->num_vertices < num_vertices)
    poly->vertices = polymec_realloc(poly->vertices, sizeof(point_t)*num_vertices);
  poly->num_vertices = num_vertices;
  int pos = 0, offset = 0;
  point2_t* vtx;
  int* ordering2 = polygon2_ordering(poly2);
  while (polygon2_next_vertex(poly2, &pos, &vtx))
  {
    int I = ordering2[offset++];
    plane_embed(poly->plane, vtx, &poly->vertices[I]);
  }

  // Recompute geometry (plane remains unchanged).
  compute_centroid(poly->vertices, poly->num_vertices, &poly->x0);

  // Clean up.
  poly2 = NULL;
  other2 = NULL;
}
Пример #3
0
static int exchanger_send_message(exchanger_t* ex, void* data, mpi_message_t* msg)
{
  START_FUNCTION_TIMER();
  // If we are expecting data, post asynchronous receives. 
  int j = 0;
  for (int i = 0; i < msg->num_receives; ++i)
  {
    ASSERT(ex->rank != msg->source_procs[i]);
    int err = MPI_Irecv(msg->receive_buffers[i], 
                        msg->stride * msg->receive_buffer_sizes[i],
                        msg->type, msg->source_procs[i], msg->tag, ex->comm, 
                        &(msg->requests[j++]));
    if (err != MPI_SUCCESS)
    {
      int resultlen;
      char str[MPI_MAX_ERROR_STRING];
      MPI_Error_string(err, str, &resultlen);
      char err_msg[1024];
      snprintf(err_msg, 1024, "%d: MPI Error posting receive from %d: %d\n(%s)\n", 
          ex->rank, msg->source_procs[i], err, str);
      polymec_error(err_msg);
    }
  }

  // Send the data asynchronously. 
  for (int i = 0; i < msg->num_sends; ++i)
  {
    int err = MPI_Isend(msg->send_buffers[i], 
                        msg->stride * msg->send_buffer_sizes[i], 
                        msg->type, msg->dest_procs[i], msg->tag, ex->comm, 
                        &(msg->requests[j++])); 
    if (err != MPI_SUCCESS)
    {
      int resultlen;
      char str[MPI_MAX_ERROR_STRING];
      MPI_Error_string(err, str, &resultlen);
      char err_msg[1024];
      snprintf(err_msg, 1024, "%d: MPI Error sending to %d: %d\n(%s)\n", 
          ex->rank, msg->dest_procs[i], err, str);
      polymec_error(err_msg);
    }
  }
  msg->num_requests = j;

  // Allocate a token.
  int token = 0;
  while ((token < ex->num_pending_msgs) && (ex->pending_msgs[token] != NULL))
    ++token;
  if (token == ex->num_pending_msgs) ++ex->num_pending_msgs;
  if (ex->num_pending_msgs == ex->pending_msg_cap)
  {
    ex->pending_msg_cap *= 2;
    ex->pending_msgs = polymec_realloc(ex->pending_msgs, ex->pending_msg_cap*sizeof(mpi_message_t));
    ex->orig_buffers = polymec_realloc(ex->orig_buffers, ex->pending_msg_cap*sizeof(void*));
    ex->transfer_counts = polymec_realloc(ex->transfer_counts, ex->pending_msg_cap*sizeof(int*));
  }
  ex->pending_msgs[token] = msg;
  ex->orig_buffers[token] = data;
  STOP_FUNCTION_TIMER();
  return token;
}
Пример #4
0
void polygon2_clip(polygon2_t* poly, polygon2_t* other)
{
  // This implementation is based on that shown in Chapter 7.6.1 of 
  // Joseph O'Rourke's _Computational_Geometry_In_C_.

  int a = 0, b = 0, aa = 0, ba = 0;
  int n = poly->num_vertices, m = other->num_vertices;
  polygon2_inout_t inflag = UNKNOWN;
  static point2_t origin = {.x = 0.0, .y = 0.0};
  point2_t p0; // First point.

  // We'll store the coordinates of the vertices of the 
  // clipped polygon here.
  real_slist_t* xlist = real_slist_new();
  real_slist_t* ylist = real_slist_new();

  do
  {
    // Computations of key variables.
    int a1 = (a + n - 1) % n;
    int b1 = (b + m - 1) % m;

    int aa = poly->ordering[a];
    int aa1 = poly->ordering[a1];
    int bb = poly->ordering[b];
    int bb1 = poly->ordering[b1];

    point2_t* Pa = &poly->vertices[aa];
    point2_t* Pa1 = &poly->vertices[aa1];
    point2_t* Qb = &other->vertices[bb];
    point2_t* Qb1 = &other->vertices[bb1];

    point2_t A, B;
    A.x = Pa1->x - Pa->x;
    A.y = Pa1->y - Pa->y;
    B.x = Qb1->x - Qb->x;
    B.y = Qb1->y - Qb->y;

    int cross = SIGN(triangle_area(&origin, &A, &B));
    int aHB   = SIGN(triangle_area(Qb1, Qb, Pa));
    int bHA   = SIGN(triangle_area(Pa1, Pa, Qb));

    // If A and B intersect, update inflag.
    point2_t p;
    char code = seg_set_int(Pa1, Pa, Qb1, Qb, &p);
    if ((code == '1') || (code == 'v')) 
    {
      if ((inflag == UNKNOWN) && (real_slist_empty(xlist)))
      {
        aa = ba = 0;
        p0.x = p.x;
        p0.y = p.y;
        real_slist_append(xlist, p0.x);
        real_slist_append(ylist, p0.y);
      }
      inflag = in_out(&p, inflag, aHB, bHA, xlist, ylist);
    }

    // Advance rules.
    else if (cross >= 0)
    {
      if (bHA > 0)
        a = advance(a, &aa, n, (inflag == PIN), Pa, xlist, ylist);
      else
        b = advance(b, &ba, m, (inflag == QIN), Qb, xlist, ylist);
    }
    else // if (cross < 0)
    {
      if (aHB > 0)
        b = advance(b, &ba, m, (inflag == QIN), Qb, xlist, ylist);
      else
        a = advance(a, &aa, n, (inflag == PIN), Pa, xlist, ylist);
    }
  }
  while (((aa < n) || (ba < m)) && (aa < 2*n) && (ba < 2*m));

  // Replace this polygon with its clipped version.
  ASSERT(xlist->size > 0);
  ASSERT(xlist->size == ylist->size);
  if (xlist->size > poly->num_vertices)
    poly->vertices = polymec_realloc(poly->vertices, sizeof(point2_t)*xlist->size);
  poly->num_vertices = xlist->size;
  for (int i = 0; i < xlist->size; ++i)
  {
    // FIXME: Verify!
    poly->vertices[i].x = real_slist_pop(xlist, NULL);
    poly->vertices[i].y = real_slist_pop(ylist, NULL);
  }
  polygon2_compute_area(poly);

  // Clean up.
  real_slist_free(xlist);
  real_slist_free(ylist);
}
Пример #5
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;
}