int main (int argc, char **argv) { int i, i1, i2, i3, i3last, i4, i4last, temp, count; size_t s, swaps1, swaps2, swaps3, total1, total2, total3; ssize_t searched; int *pi; sc_array_t *a1, *a2, *a3, *a4; int mpiret; double start, elapsed_pqueue, elapsed_qsort; mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_DEFAULT); a1 = sc_array_new (sizeof (int)); a2 = sc_array_new (sizeof (int)); a3 = sc_array_new (sizeof (int)); a4 = sc_array_new (sizeof (int)); #ifdef THEBIGTEST count = 325323; #else count = 3251; #endif SC_INFOF ("Test pqueue with count %d\n", count); start = -sc_MPI_Wtime (); swaps1 = swaps2 = swaps3 = 0; total1 = total2 = total3 = 0; for (i = 0; i < count; ++i) { *(int *) sc_array_push (a1) = i; s = sc_array_pqueue_add (a1, &temp, compar); swaps1 += ((s > 0) ? 1 : 0); total1 += s; *(int *) sc_array_push (a2) = count - i - 1; s = sc_array_pqueue_add (a2, &temp, compar); swaps2 += ((s > 0) ? 1 : 0); total2 += s; *(int *) sc_array_push (a3) = (15 * i) % 172; s = sc_array_pqueue_add (a3, &temp, compar); swaps3 += ((s > 0) ? 1 : 0); total3 += s; } SC_CHECK_ABORT (swaps1 == 0 && total1 == 0, "pqueue_add"); SC_VERBOSEF (" Swaps %lld %lld %lld Total %lld %lld %lld\n", (long long) swaps1, (long long) swaps2, (long long) swaps3, (long long) total1, (long long) total2, (long long) total3); temp = 52; searched = sc_array_bsearch (a1, &temp, compar); SC_CHECK_ABORT (searched != -1, "array_bsearch_index"); pi = (int *) sc_array_index_ssize_t (a1, searched); SC_CHECK_ABORT (*pi == temp, "array_bsearch"); i3last = -1; swaps1 = swaps2 = swaps3 = 0; total1 = total2 = total3 = 0; for (i = 0; i < count; ++i) { s = sc_array_pqueue_pop (a1, &i1, compar); swaps1 += ((s > 0) ? 1 : 0); total1 += s; s = sc_array_pqueue_pop (a2, &i2, compar); swaps2 += ((s > 0) ? 1 : 0); total2 += s; s = sc_array_pqueue_pop (a3, &i3, compar); swaps3 += ((s > 0) ? 1 : 0); total3 += s; SC_CHECK_ABORT (i == i1 && i == i2, "pqueue_pop"); SC_CHECK_ABORT (i3 >= i3last, "pqueue_pop"); i3last = i3; } SC_VERBOSEF (" Swaps %lld %lld %lld Total %lld %lld %lld\n", (long long) swaps1, (long long) swaps2, (long long) swaps3, (long long) total1, (long long) total2, (long long) total3); elapsed_pqueue = start + sc_MPI_Wtime (); sc_array_destroy (a1); sc_array_destroy (a2); sc_array_destroy (a3); SC_INFOF ("Test array sort with count %d\n", count); start = -sc_MPI_Wtime (); /* the resize is done to be comparable with the above procedure */ for (i = 0; i < count; ++i) { *(int *) sc_array_push (a4) = (15 * i) % 172; } sc_array_sort (a4, compar); i4last = -1; for (i = 0; i < count; ++i) { i4 = *(int *) sc_array_index_int (a4, i); SC_CHECK_ABORT (i4 >= i4last, "array_sort"); i4last = i4; } sc_array_resize (a4, 0); elapsed_qsort = start + sc_MPI_Wtime (); SC_STATISTICSF ("Test timings pqueue %g qsort %g\n", elapsed_pqueue, 3. * elapsed_qsort); sc_array_destroy (a4); sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
static void mesh_iter_corner (p4est_iter_corner_info_t * info, void *user_data) { int i, j; int f1, f2, code, orientation; int fc1, fc2, diagonal; #ifdef P4_TO_P8 int pref, pset; #endif int visited[P4EST_CHILDREN]; int8_t *pccorner; size_t cz, zz; sc_array_t *trees; p4est_locidx_t qoffset, qid1, qid2; p4est_locidx_t cornerid_offset, cornerid; p4est_locidx_t *pcquad; p4est_mesh_t *mesh = (p4est_mesh_t *) user_data; p4est_iter_corner_side_t *side1, *side2; p4est_tree_t *tree1, *tree2; p4est_connectivity_t *conn; /* Check the case when the corner does not involve neighbors */ cz = info->sides.elem_count; P4EST_ASSERT (cz > 0); P4EST_ASSERT (info->tree_boundary || cz == P4EST_CHILDREN); if (cz == 1) { return; } conn = info->p4est->connectivity; trees = info->p4est->trees; cornerid_offset = mesh->local_num_quadrants + mesh->ghost_num_quadrants; if (info->tree_boundary == P4EST_CONNECT_FACE) { /* This corner is inside an inter-tree face */ if (cz == P4EST_HALF) { /* This is a tree face boundary, no corner neighbors exist */ return; } P4EST_ASSERT (cz == P4EST_CHILDREN); /* Process a corner in pairs of diagonal inter-tree neighbors */ memset (visited, 0, P4EST_CHILDREN * sizeof (int)); for (i = 0; i < P4EST_HALF; ++i) { side1 = side2 = NULL; f1 = -1; fc1 = -1; qid1 = -3; for (j = 0; j < P4EST_CHILDREN; ++j) { if (visited[j]) { continue; } /* Remember the first side we want to pair up */ if (side1 == NULL) { side1 = (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j); P4EST_ASSERT (side1->quad != NULL); f1 = tree_face_quadrant_corner_face (side1->quad, side1->corner); fc1 = p4est_corner_face_corners[side1->corner][f1]; P4EST_ASSERT (0 <= fc1 && fc1 < P4EST_HALF); tree1 = p4est_tree_array_index (trees, side1->treeid); qid1 = side1->quadid + (side1->is_ghost ? mesh->local_num_quadrants : tree1->quadrants_offset); visited[j] = 1; continue; } /* Examine a potential second side */ P4EST_ASSERT (side2 == NULL); side2 = (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j); P4EST_ASSERT (side2->quad != NULL); f2 = tree_face_quadrant_corner_face (side2->quad, side2->corner); if (side1->treeid == side2->treeid && f1 == f2) { /* Periodicity allows for equal trees and unequal faces */ side2 = NULL; continue; } /* This side as in the opposite tree */ fc2 = p4est_corner_face_corners[side2->corner][f2]; P4EST_ASSERT (0 <= fc2 && fc2 < P4EST_HALF); code = conn->tree_to_face[P4EST_FACES * side1->treeid + f1]; orientation = code / P4EST_FACES; P4EST_ASSERT (f2 == code % P4EST_FACES); #ifdef P4_TO_P8 pref = p8est_face_permutation_refs[f1][f2]; pset = p8est_face_permutation_sets[pref][orientation]; diagonal = (p8est_face_permutations[pset][fc1] ^ fc2) == 3; #else diagonal = (fc1 ^ fc2) != orientation; #endif if (!diagonal) { side2 = NULL; continue; } /* We have found a diagonally opposite second side */ tree2 = p4est_tree_array_index (trees, side2->treeid); qid2 = side2->quadid + (side2->is_ghost ? mesh->local_num_quadrants : tree2->quadrants_offset); if (!side1->is_ghost) { P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants); P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] == -1); cornerid = mesh_corner_allocate (mesh, 1, &pcquad, &pccorner); mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] = cornerid_offset + cornerid; *pcquad = qid2; *pccorner = side2->corner; } if (!side2->is_ghost) { P4EST_ASSERT (0 <= qid2 && qid2 < mesh->local_num_quadrants); P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid2 + side2->corner] == -1); cornerid = mesh_corner_allocate (mesh, 1, &pcquad, &pccorner); mesh->quad_to_corner[P4EST_CHILDREN * qid2 + side2->corner] = cornerid_offset + cornerid; *pcquad = qid1; *pccorner = side1->corner; } visited[j] = 1; break; } P4EST_ASSERT (side1 != NULL && side2 != NULL); } return; } #ifdef P4_TO_P8 if (info->tree_boundary == P8EST_CONNECT_EDGE) { /* Tree corner neighbors across an edge are not implemented: set to -2 */ for (zz = 0; zz < cz; ++zz) { side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, zz); if (!side1->is_ghost) { tree1 = p4est_tree_array_index (trees, side1->treeid); qid1 = side1->quadid + tree1->quadrants_offset; P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants); P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] == -1); mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] = -2; } } return; } #endif if (info->tree_boundary == P4EST_CONNECT_CORNER) { int c1, ncorner[P4EST_DIM]; int nface[P4EST_DIM]; int ignore; size_t z2; int8_t *ccorners; p4est_topidx_t t1, ntree[P4EST_DIM]; p4est_locidx_t goodones; p4est_locidx_t *cquads; /* Loop through all corner sides, that is the quadrants touching it. For * each of these quadrants, determine the corner sides that can potentially * occur by being a face neighbor as well. Exclude these face neighbors * and the quadrant itself, record all others as corner neighbors. */ cquads = P4EST_ALLOC (p4est_locidx_t, cz - 1); ccorners = P4EST_ALLOC (int8_t, cz - 1); for (zz = 0; zz < cz; ++zz) { side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, zz); if (!side1->is_ghost) { /* We only create corner information for processor-local quadrants */ t1 = side1->treeid; c1 = (int) side1->corner; tree1 = p4est_tree_array_index (trees, t1); qid1 = side1->quadid + tree1->quadrants_offset; P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants); P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 + c1] == -1); /* Check all quadrant faces that touch this corner */ for (i = 0; i < P4EST_DIM; ++i) { f1 = p4est_corner_faces[c1][i]; ntree[i] = conn->tree_to_tree[P4EST_FACES * t1 + f1]; nface[i] = conn->tree_to_face[P4EST_FACES * t1 + f1]; if (ntree[i] == t1 && nface[i] == f1) { /* This is a physical face boundary, no face neighbor present */ ncorner[i] = -1; continue; } /* We have a face neighbor */ orientation = nface[i] / P4EST_FACES; nface[i] %= P4EST_FACES; ncorner[i] = p4est_connectivity_face_neighbor_corner (c1, f1, nface[i], orientation); } /* Go through corner neighbors and collect the true corners */ goodones = 0; for (z2 = 0; z2 < cz; ++z2) { if (z2 == zz) { /* We do not count ourselves as a neighbor */ continue; } ignore = 0; side2 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, z2); P4EST_ASSERT (side2->corner >= 0); for (i = 0; i < P4EST_DIM; ++i) { /* Ignore if this is one of the face neighbors' corners */ if (ncorner[i] == (int) side2->corner && ntree[i] == side2->treeid) { ignore = 1; break; } } if (ignore) { continue; } /* Record this corner neighbor */ tree2 = p4est_tree_array_index (trees, side2->treeid); qid2 = side2->quadid + (side2->is_ghost ? mesh->local_num_quadrants : tree2->quadrants_offset); cquads[goodones] = qid2; ccorners[goodones] = (int) side2->corner; ++goodones; } P4EST_ASSERT ((size_t) goodones < cz); if (goodones == 0) { continue; } /* Allocate and fill corner information in the mesh structure */ cornerid = mesh_corner_allocate (mesh, goodones, &pcquad, &pccorner); mesh->quad_to_corner[P4EST_CHILDREN * qid1 + c1] = cornerid_offset + cornerid; memcpy (pcquad, cquads, goodones * sizeof (p4est_locidx_t)); memcpy (pccorner, ccorners, goodones * sizeof (int8_t)); } } P4EST_FREE (cquads); P4EST_FREE (ccorners); return; } /* Process a corner inside the tree in pairs of diagonal neighbors */ P4EST_ASSERT (!info->tree_boundary); side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, 0); tree1 = p4est_tree_array_index (trees, side1->treeid); qoffset = tree1->quadrants_offset; memset (visited, 0, P4EST_CHILDREN * sizeof (int)); for (i = 0; i < P4EST_HALF; ++i) { side1 = side2 = NULL; qid1 = -3; for (j = 0; j < P4EST_CHILDREN; ++j) { if (visited[j]) { continue; } /* Remember the first side we want to pair up */ if (side1 == NULL) { side1 = (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j); qid1 = side1->quadid + (side1->is_ghost ? mesh->local_num_quadrants : qoffset); visited[j] = 1; continue; } /* Examine a potential second side */ P4EST_ASSERT (side2 == NULL); side2 = (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j); P4EST_ASSERT (side1->treeid == side2->treeid); if (side1->corner + side2->corner != P4EST_CHILDREN - 1) { side2 = NULL; continue; } /* We have found a diagonally opposite second side */ qid2 = side2->quadid + (side2->is_ghost ? mesh->local_num_quadrants : qoffset); if (!side1->is_ghost) { P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants); P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] == -1); mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] = qid2; } if (!side2->is_ghost) { P4EST_ASSERT (0 <= qid2 && qid2 < mesh->local_num_quadrants); P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid2 + side2->corner] == -1); mesh->quad_to_corner[P4EST_CHILDREN * qid2 + side2->corner] = qid1; } visited[j] = 1; break; } P4EST_ASSERT (side1 != NULL && side2 != NULL); } }