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]); } }
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; }
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; }
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); }
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; }