/* given two profiles (layers that have been reduced to just their levels), * take the union, i.e. combine them, taking the finer layers */ static void p6est_profile_union (sc_array_t * a, sc_array_t * b, sc_array_t * c) { size_t az, bz, na; P4EST_ASSERT (SC_ARRAY_IS_OWNER (c)); P4EST_ASSERT (a->elem_size == sizeof (int8_t)); P4EST_ASSERT (b->elem_size == sizeof (int8_t)); P4EST_ASSERT (c->elem_size == sizeof (int8_t)); int8_t al, bl, finel, *cc; p4est_qcoord_t finesize, coarsesize; sc_array_t *finer; size_t *fineincr; sc_array_truncate (c); az = 0; bz = 0; na = a->elem_count; while (az < na) { P4EST_ASSERT (bz < b->elem_count); cc = (int8_t *) sc_array_push (c); al = *((int8_t *) sc_array_index (a, az++)); bl = *((int8_t *) sc_array_index (b, bz++)); if (al == bl) { *cc = al; continue; } else if (al > bl) { finer = a; finesize = P4EST_QUADRANT_LEN (al); fineincr = &az; finel = al; coarsesize = P4EST_QUADRANT_LEN (bl); } else { finer = b; finesize = P4EST_QUADRANT_LEN (bl); fineincr = &bz; finel = bl; coarsesize = P4EST_QUADRANT_LEN (al); } P4EST_ASSERT (finesize < coarsesize); do { *cc = finel; cc = (int8_t *) sc_array_push (c); finel = *((int8_t *) sc_array_index (finer, (*fineincr)++)); finesize += P4EST_QUADRANT_LEN (finel); } while (finesize < coarsesize); P4EST_ASSERT (finesize == coarsesize); *cc = finel; } }
static p4est_locidx_t mesh_corner_allocate (p4est_mesh_t * mesh, p4est_locidx_t clen, p4est_locidx_t ** pcquad, int8_t ** pccorner) { p4est_locidx_t cornerid, cstart, cend; P4EST_ASSERT (clen > 0); P4EST_ASSERT (mesh->corner_offset->elem_count == (size_t) (mesh->local_num_corners + 1)); cornerid = mesh->local_num_corners++; cstart = *(p4est_locidx_t *) sc_array_index (mesh->corner_offset, cornerid); cend = cstart + clen; *(p4est_locidx_t *) sc_array_push (mesh->corner_offset) = cend; P4EST_ASSERT (mesh->corner_offset->elem_count == (size_t) (mesh->local_num_corners + 1)); P4EST_ASSERT (mesh->corner_quad->elem_count == (size_t) cstart); *pcquad = (p4est_locidx_t *) sc_array_push_count (mesh->corner_quad, clen); P4EST_ASSERT (mesh->corner_quad->elem_count == (size_t) cend); P4EST_ASSERT (mesh->corner_corner->elem_count == (size_t) cstart); *pccorner = (int8_t *) sc_array_push_count (mesh->corner_corner, clen); P4EST_ASSERT (mesh->corner_corner->elem_count == (size_t) cend); return cornerid; }
static void p6est_profile_balance_self_one_pass (sc_array_t * read, sc_array_t * write) { int stackcount; int8_t n, newn, p, l; int8_t *wc; size_t count = read->elem_count; size_t zy; P4EST_ASSERT (SC_ARRAY_IS_OWNER (write)); P4EST_ASSERT (read->elem_size == sizeof (int8_t)); P4EST_ASSERT (write->elem_size == sizeof (int8_t)); sc_array_truncate (write); wc = (int8_t *) sc_array_push (write); n = *((int8_t *) sc_array_index (read, count - 1)); *wc = l = n; for (zy = 1; zy < count; zy++) { n = *((int8_t *) sc_array_index (read, count - 1 - zy)); p = l - 1; newn = SC_MAX (p, n); stackcount = newn - n; wc = (int8_t *) sc_array_push_count (write, 1 + stackcount); *wc = l = newn; while (stackcount--) { *(++wc) = l = newn--; } } }
static void mesh_iter_volume (p4est_iter_volume_info_t * info, void *user_data) { p4est_mesh_t *mesh = (p4est_mesh_t *) user_data; p4est_tree_t *tree; p4est_locidx_t *quadid; int level = info->quad->level; /* We could use a static quadrant counter, but that gets uglier */ tree = p4est_tree_array_index (info->p4est->trees, info->treeid); P4EST_ASSERT (0 <= info->quadid && info->quadid < (p4est_locidx_t) tree->quadrants.elem_count); if (mesh->quad_to_tree != NULL) { mesh->quad_to_tree[tree->quadrants_offset + info->quadid] = info->treeid; } if (mesh->quad_level != NULL) { quadid = (p4est_locidx_t *) sc_array_push (mesh->quad_level + level); *quadid = tree->quadrants_offset + info->quadid; } }
int check_balance_seeds (p4est_quadrant_t * q, p4est_quadrant_t * p, p4est_connect_type_t b, sc_array_t * seeds) { int ib; int level = q->level; p4est_quadrant_t *s, *t; sc_array_t *thislevel = sc_array_new (sizeof (p4est_quadrant_t)); sc_array_t *nextlevel = sc_array_new (sizeof (p4est_quadrant_t)); sc_array_t *temparray; p4est_quadrant_t temp1, temp2; int f, c; #ifdef P4_TO_P8 int e; #endif int stop = 0; sc_array_resize (seeds, 0); s = (p4est_quadrant_t *) sc_array_push (thislevel); p4est_quadrant_sibling (q, s, 0); #ifndef P4_TO_P8 if (b == P4EST_CONNECT_FACE) { ib = 0; } else { ib = 1; } #else if (b == P8EST_CONNECT_FACE) { ib = 0; } else if (b == P8EST_CONNECT_EDGE) { ib = 1; } else { ib = 2; } #endif while (level > p->level + 1) { size_t nlast = thislevel->elem_count; size_t zz; stop = 0; for (zz = 0; zz < nlast; zz++) { s = p4est_quadrant_array_index (thislevel, zz); P4EST_ASSERT (p4est_quadrant_child_id (s) == 0); p4est_quadrant_parent (s, &temp1); for (f = 0; f < P4EST_FACES; f++) { p4est_quadrant_face_neighbor (&temp1, f, &temp2); if (is_farther (&temp1, p, &temp2)) { continue; } if (p4est_quadrant_is_ancestor (p, &temp2)) { stop = 1; sc_array_resize (seeds, seeds->elem_count + 1); t = p4est_quadrant_array_index (seeds, seeds->elem_count - 1); p4est_quadrant_sibling (&temp2, t, 0); } else if (p4est_quadrant_is_inside_root (&temp2)) { t = (p4est_quadrant_t *) sc_array_push (nextlevel); p4est_quadrant_sibling (&temp2, t, 0); } } if (ib == 0) { continue; } #ifdef P4_TO_P8 for (e = 0; e < P8EST_EDGES; e++) { p8est_quadrant_edge_neighbor (&temp1, e, &temp2); if (is_farther (&temp1, p, &temp2)) { continue; } if (p4est_quadrant_is_ancestor (p, &temp2)) { stop = 1; sc_array_resize (seeds, seeds->elem_count + 1); t = p4est_quadrant_array_index (seeds, seeds->elem_count - 1); p4est_quadrant_sibling (&temp2, t, 0); } else if (p4est_quadrant_is_inside_root (&temp2)) { t = (p4est_quadrant_t *) sc_array_push (nextlevel); p4est_quadrant_sibling (&temp2, t, 0); } } if (ib == 1) { continue; } #endif for (c = 0; c < P4EST_CHILDREN; c++) { p4est_quadrant_corner_neighbor (&temp1, c, &temp2); if (is_farther (&temp1, p, &temp2)) { continue; } if (p4est_quadrant_is_ancestor (p, &temp2)) { stop = 1; sc_array_resize (seeds, seeds->elem_count + 1); t = p4est_quadrant_array_index (seeds, seeds->elem_count - 1); p4est_quadrant_sibling (&temp2, t, 0); } else if (p4est_quadrant_is_inside_root (&temp2)) { t = (p4est_quadrant_t *) sc_array_push (nextlevel); p4est_quadrant_sibling (&temp2, t, 0); } } } if (stop) { sc_array_sort (seeds, p4est_quadrant_compare); sc_array_uniq (seeds, p4est_quadrant_compare); #ifdef P4_TO_P8 if (!ib && seeds->elem_count == 1) { sc_array_sort (nextlevel, p4est_quadrant_compare); sc_array_uniq (nextlevel, p4est_quadrant_compare); temparray = thislevel; thislevel = nextlevel; nextlevel = temparray; sc_array_reset (nextlevel); level--; nlast = thislevel->elem_count; for (zz = 0; zz < nlast; zz++) { s = p4est_quadrant_array_index (thislevel, zz); P4EST_ASSERT (p4est_quadrant_child_id (s) == 0); p4est_quadrant_parent (s, &temp1); for (f = 0; f < P4EST_FACES; f++) { p4est_quadrant_face_neighbor (&temp1, f, &temp2); if (p4est_quadrant_is_ancestor (p, &temp2)) { int f2; p4est_quadrant_t a; p4est_quadrant_t u; t = p4est_quadrant_array_index (seeds, 0); p8est_quadrant_parent (t, &a); for (f2 = 0; f2 < P8EST_FACES; f2++) { if (f2 / 2 == f / 2) { continue; } p8est_quadrant_face_neighbor (&a, f2, &u); if (p8est_quadrant_is_equal (&temp2, &u) || p8est_quadrant_is_sibling (&temp2, &u)) { break; } } if (f2 == P8EST_FACES) { sc_array_resize (seeds, seeds->elem_count + 1); t = p4est_quadrant_array_index (seeds, seeds->elem_count - 1); p4est_quadrant_sibling (&temp2, t, 0); } } } } } #endif sc_array_sort (seeds, p4est_quadrant_compare); sc_array_uniq (seeds, p4est_quadrant_compare); break; } sc_array_sort (nextlevel, p4est_quadrant_compare); sc_array_uniq (nextlevel, p4est_quadrant_compare); temparray = thislevel; thislevel = nextlevel; nextlevel = temparray; sc_array_reset (nextlevel); level--; } sc_array_destroy (thislevel); sc_array_destroy (nextlevel); return stop; }
void p8est_quadrant_edge_neighbor_extra (const p4est_quadrant_t * q, p4est_topidx_t t, int edge, sc_array_t * quads, sc_array_t * treeids, p4est_connectivity_t * conn) { p4est_quadrant_t temp; p4est_quadrant_t *qp; p4est_topidx_t *tp; int face; p8est_edge_info_t ei; p8est_edge_transform_t *et; sc_array_t *eta; size_t etree; eta = &ei.edge_transforms; P4EST_ASSERT (SC_ARRAY_IS_OWNER (quads)); P4EST_ASSERT (quads->elem_count == 0); P4EST_ASSERT (quads->elem_size == sizeof (p4est_quadrant_t)); P4EST_ASSERT (SC_ARRAY_IS_OWNER (treeids)); P4EST_ASSERT (treeids->elem_count == 0); P4EST_ASSERT (treeids->elem_size == sizeof (p4est_topidx_t)); p8est_quadrant_edge_neighbor (q, edge, &temp); if (p4est_quadrant_is_inside_root (&temp)) { qp = p4est_quadrant_array_push (quads); *qp = temp; tp = (p4est_topidx_t *) sc_array_push (treeids); *tp = t; return; } if (!p8est_quadrant_is_outside_edge (&temp)) { qp = p4est_quadrant_array_push (quads); tp = (p4est_topidx_t *) sc_array_push (treeids); face = p8est_edge_faces[edge][0]; p4est_quadrant_face_neighbor (q, face, &temp); if (p4est_quadrant_is_inside_root (&temp)) { face = p8est_edge_faces[edge][1]; *tp = p8est_quadrant_face_neighbor_extra (&temp, t, face, qp, conn); if (*tp == -1) { qp = (p4est_quadrant_t *) sc_array_pop (quads); tp = (p4est_topidx_t *) sc_array_pop (treeids); } return; } face = p8est_edge_faces[edge][1]; p4est_quadrant_face_neighbor (q, face, &temp); P4EST_ASSERT (p4est_quadrant_is_inside_root (&temp)); face = p8est_edge_faces[edge][0]; *tp = p8est_quadrant_face_neighbor_extra (&temp, t, face, qp, conn); if (*tp == -1) { qp = (p4est_quadrant_t *) sc_array_pop (quads); tp = (p4est_topidx_t *) sc_array_pop (treeids); } return; } sc_array_init (eta, sizeof (p8est_edge_transform_t)); p8est_find_edge_transform (conn, t, edge, &ei); sc_array_resize (quads, eta->elem_count); sc_array_resize (treeids, eta->elem_count); for (etree = 0; etree < eta->elem_count; etree++) { qp = p4est_quadrant_array_index (quads, etree); tp = (p4est_topidx_t *) sc_array_index (treeids, etree); et = p8est_edge_array_index (eta, etree); p8est_quadrant_transform_edge (&temp, qp, &ei, et, 1); *tp = et->ntree; } sc_array_reset (eta); }
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; }
p4est_mesh_t * p4est_mesh_new_ext (p4est_t * p4est, p4est_ghost_t * ghost, int compute_tree_index, int compute_level_lists, p4est_connect_type_t btype) { int do_corner = 0; int do_volume = 0; int rank; p4est_locidx_t lq, ng; p4est_locidx_t jl; p4est_mesh_t *mesh; P4EST_ASSERT (p4est_is_balanced (p4est, btype)); mesh = P4EST_ALLOC_ZERO (p4est_mesh_t, 1); lq = mesh->local_num_quadrants = p4est->local_num_quadrants; ng = mesh->ghost_num_quadrants = (p4est_locidx_t) ghost->ghosts.elem_count; if (btype == P4EST_CONNECT_FULL) { do_corner = 1; } do_volume = (compute_tree_index || compute_level_lists ? 1 : 0); /* Optional map of tree index for each quadrant */ if (compute_tree_index) { mesh->quad_to_tree = P4EST_ALLOC (p4est_topidx_t, lq); } mesh->ghost_to_proc = P4EST_ALLOC (int, ng); mesh->quad_to_quad = P4EST_ALLOC (p4est_locidx_t, P4EST_FACES * lq); mesh->quad_to_face = P4EST_ALLOC (int8_t, P4EST_FACES * lq); mesh->quad_to_half = sc_array_new (P4EST_HALF * sizeof (p4est_locidx_t)); /* Optional per-level lists of quadrants */ if (compute_level_lists) { mesh->quad_level = P4EST_ALLOC (sc_array_t, P4EST_QMAXLEVEL + 1); for (jl = 0; jl <= P4EST_QMAXLEVEL; ++jl) { sc_array_init (mesh->quad_level + jl, sizeof (p4est_locidx_t)); } } /* Populate ghost information */ rank = 0; for (jl = 0; jl < ng; ++jl) { while (ghost->proc_offsets[rank + 1] <= jl) { ++rank; P4EST_ASSERT (rank < p4est->mpisize); } mesh->ghost_to_proc[jl] = rank; } /* Fill face arrays with default values */ memset (mesh->quad_to_quad, -1, P4EST_FACES * lq * sizeof (p4est_locidx_t)); memset (mesh->quad_to_face, -25, P4EST_FACES * lq * sizeof (int8_t)); if (do_corner) { /* Initialize corner information to a consistent state */ mesh->quad_to_corner = P4EST_ALLOC (p4est_locidx_t, P4EST_CHILDREN * lq); memset (mesh->quad_to_corner, -1, P4EST_CHILDREN * lq * sizeof (p4est_locidx_t)); mesh->corner_offset = sc_array_new (sizeof (p4est_locidx_t)); *(p4est_locidx_t *) sc_array_push (mesh->corner_offset) = 0; mesh->corner_quad = sc_array_new (sizeof (p4est_locidx_t)); mesh->corner_corner = sc_array_new (sizeof (int8_t)); } /* Call the forest iterator to collect face connectivity */ p4est_iterate (p4est, ghost, mesh, (do_volume ? mesh_iter_volume : NULL), mesh_iter_face, #ifdef P4_TO_P8 NULL, #endif do_corner ? mesh_iter_corner : NULL); return mesh; }
static void mesh_iter_face (p4est_iter_face_info_t * info, void *user_data) { int h; int swapsides; p4est_mesh_t *mesh = (p4est_mesh_t *) user_data; p4est_locidx_t jl, jl2, jls[P4EST_HALF]; p4est_locidx_t in_qtoq, halfindex; p4est_locidx_t *halfentries; p4est_tree_t *tree; p4est_iter_face_side_t *side, *side2, *tempside; if (info->sides.elem_count == 1) { /* this face is on an outside boundary of the forest */ P4EST_ASSERT (info->orientation == 0); P4EST_ASSERT (info->tree_boundary); side = (p4est_iter_face_side_t *) sc_array_index (&info->sides, 0); P4EST_ASSERT (0 <= side->treeid && side->treeid < info->p4est->connectivity->num_trees); P4EST_ASSERT (0 <= side->face && side->face < P4EST_FACES); P4EST_ASSERT (!side->is_hanging && !side->is.full.is_ghost); tree = p4est_tree_array_index (info->p4est->trees, side->treeid); jl = side->is.full.quadid + tree->quadrants_offset; P4EST_ASSERT (0 <= jl && jl < mesh->local_num_quadrants); in_qtoq = P4EST_FACES * jl + side->face; mesh->quad_to_quad[in_qtoq] = jl; /* put in myself and my own face */ mesh->quad_to_face[in_qtoq] = side->face; } else { /* this face is between two quadrants */ P4EST_ASSERT (info->orientation == 0 || info->tree_boundary); P4EST_ASSERT (info->sides.elem_count == 2); side = (p4est_iter_face_side_t *) sc_array_index (&info->sides, 0); side2 = (p4est_iter_face_side_t *) sc_array_index (&info->sides, 1); P4EST_ASSERT (info->tree_boundary || side->treeid == side2->treeid); P4EST_ASSERT (!side->is_hanging || !side2->is_hanging); if (!side->is_hanging && !side2->is_hanging) { /* same-size face neighbors */ P4EST_ASSERT (!side->is.full.is_ghost || !side2->is.full.is_ghost); /* determine both quadrant numbers */ if (!side->is.full.is_ghost) { tree = p4est_tree_array_index (info->p4est->trees, side->treeid); jl = side->is.full.quadid + tree->quadrants_offset; P4EST_ASSERT (0 <= jl && jl < mesh->local_num_quadrants); } else { P4EST_ASSERT (side->is.full.quad != NULL); P4EST_ASSERT (side->is.full.quadid >= 0); jl = mesh->local_num_quadrants + side->is.full.quadid; } if (!side2->is.full.is_ghost) { tree = p4est_tree_array_index (info->p4est->trees, side2->treeid); jl2 = side2->is.full.quadid + tree->quadrants_offset; P4EST_ASSERT (0 <= jl2 && jl2 < mesh->local_num_quadrants); } else { P4EST_ASSERT (side2->is.full.quad != NULL); P4EST_ASSERT (side2->is.full.quadid >= 0); jl2 = mesh->local_num_quadrants + side2->is.full.quadid; } /* encode quadrant neighborhood */ if (!side->is.full.is_ghost) { in_qtoq = P4EST_FACES * jl + side->face; P4EST_ASSERT (mesh->quad_to_quad[in_qtoq] == -1); P4EST_ASSERT (mesh->quad_to_face[in_qtoq] == -25); mesh->quad_to_quad[in_qtoq] = jl2; mesh->quad_to_face[in_qtoq] = P4EST_FACES * info->orientation + side2->face; } if (!side2->is.full.is_ghost) { in_qtoq = P4EST_FACES * jl2 + side2->face; P4EST_ASSERT (mesh->quad_to_quad[in_qtoq] == -1); P4EST_ASSERT (mesh->quad_to_face[in_qtoq] == -25); mesh->quad_to_quad[in_qtoq] = jl; mesh->quad_to_face[in_qtoq] = P4EST_FACES * info->orientation + side->face; } } else { /* one of the faces is hanging, rename so it's always side2 */ swapsides = side->is_hanging; if (swapsides) { tempside = side; side = side2; side2 = tempside; } P4EST_ASSERT (!side->is_hanging && side2->is_hanging); /* determine quadrant number for non-hanging large face */ if (!side->is.full.is_ghost) { tree = p4est_tree_array_index (info->p4est->trees, side->treeid); jl = side->is.full.quadid + tree->quadrants_offset; P4EST_ASSERT (0 <= jl && jl < mesh->local_num_quadrants); } else { P4EST_ASSERT (side->is.full.quad != NULL); P4EST_ASSERT (side->is.full.quadid >= 0); jl = mesh->local_num_quadrants + side->is.full.quadid; } /* determine quadrant numbers for all hanging faces */ for (h = 0; h < P4EST_HALF; ++h) { if (!side2->is.hanging.is_ghost[h]) { tree = p4est_tree_array_index (info->p4est->trees, side2->treeid); jls[h] = side2->is.hanging.quadid[h] + tree->quadrants_offset; P4EST_ASSERT (0 <= jls[h] && jls[h] < mesh->local_num_quadrants); } else { P4EST_ASSERT (side2->is.hanging.quad[h] != NULL); P4EST_ASSERT (side2->is.hanging.quadid[h] >= 0); jls[h] = mesh->local_num_quadrants + side2->is.hanging.quadid[h]; } } /* encode quadrant neighborhood */ if (!side->is.full.is_ghost) { in_qtoq = P4EST_FACES * jl + side->face; P4EST_ASSERT (mesh->quad_to_quad[in_qtoq] == -1); P4EST_ASSERT (mesh->quad_to_face[in_qtoq] == -25); halfindex = (p4est_locidx_t) mesh->quad_to_half->elem_count; mesh->quad_to_quad[in_qtoq] = halfindex; mesh->quad_to_face[in_qtoq] = P4EST_FACES * (info->orientation - P4EST_HALF) + side2->face; halfentries = (p4est_locidx_t *) sc_array_push (mesh->quad_to_half); for (h = 0; h < P4EST_HALF; ++h) { halfentries[h] = jls[h]; } } for (h = 0; h < P4EST_HALF; ++h) { if (!side2->is.hanging.is_ghost[h]) { in_qtoq = P4EST_FACES * jls[h] + side2->face; P4EST_ASSERT (mesh->quad_to_quad[in_qtoq] == -1); P4EST_ASSERT (mesh->quad_to_face[in_qtoq] == -25); mesh->quad_to_quad[in_qtoq] = jl; mesh->quad_to_face[in_qtoq] = P4EST_FACES * (info->orientation + (h + 1) * P4EST_HALF) + side->face; } } } } }
static int p8est_find_edge_transform_internal (p4est_connectivity_t * conn, p4est_topidx_t itree, int iedge, p8est_edge_info_t * ei, const p4est_topidx_t * ett, const int8_t * ete, p4est_topidx_t edge_trees) { int i, j; int redge, nedge, iflip, nflip; int pref, pset, fc[2], nc[2]; int face, nface, orient, eorient; p4est_topidx_t etree, ietree, ntree; p8est_edge_transform_t *et; sc_array_t *ta = &ei->edge_transforms; const int *fcorners; int distinct = 1; int edges[3], edgeorients[3]; p4est_topidx_t etrees[3]; P4EST_ASSERT (0 <= itree && itree < conn->num_trees); P4EST_ASSERT (0 <= iedge && iedge < P8EST_EDGES); P4EST_ASSERT (ta->elem_size == sizeof (p8est_edge_transform_t)); etrees[0] = itree; edges[0] = iedge; edgeorients[0] = 0; /* identify touching faces */ for (i = 0; i < 2; ++i) { face = p8est_edge_faces[iedge][i]; ntree = conn->tree_to_tree[P4EST_FACES * itree + face]; nface = (int) conn->tree_to_face[P4EST_FACES * itree + face]; if (ntree != itree || nface != face) { /* not domain boundary */ orient = nface / P4EST_FACES; nface %= P4EST_FACES; fcorners = &(p8est_edge_face_corners[iedge][face][0]); P4EST_ASSERT (fcorners[0] >= 0 && fcorners[1] >= 0); pref = p8est_face_permutation_refs[face][nface]; pset = p8est_face_permutation_sets[pref][orient]; fc[0] = p8est_face_permutations[pset][fcorners[0]]; fc[1] = p8est_face_permutations[pset][fcorners[1]]; /* if this is a new edge, add it */ nc[0] = p8est_face_corners[nface][fc[0]]; nc[1] = p8est_face_corners[nface][fc[1]]; nedge = p8est_child_corner_edges[nc[0]][nc[1]]; P4EST_ASSERT (nedge >= 0); eorient = (p8est_edge_corners[nedge][1] == nc[0]); for (j = 0; j < distinct; j++) { if (ntree == etrees[j] && nedge == edges[j] && eorient == edgeorients[j]) { break; } } if (j == distinct) { etrees[j] = ntree; edges[j] = nedge; edgeorients[j] = eorient; distinct++; } } } /* find orientation of this edge */ ietree = -1; iflip = -1; for (etree = 0; etree < edge_trees; ++etree) { ntree = ett[etree]; P4EST_ASSERT (0 <= ntree && ntree < conn->num_trees); redge = (int) ete[etree]; P4EST_ASSERT (redge >= 0 && redge < 2 * P8EST_EDGES); nedge = redge % P8EST_EDGES; if (nedge == iedge && ntree == itree) { iflip = redge / P8EST_EDGES; ietree = etree; break; } } P4EST_ASSERT (ietree >= 0 && iflip >= 0); /* loop through all trees connected through this edge */ for (etree = 0; etree < edge_trees; ++etree) { if (etree == ietree) { continue; } ntree = ett[etree]; P4EST_ASSERT (0 <= ntree && ntree < conn->num_trees); redge = (int) ete[etree]; P4EST_ASSERT (redge >= 0 && redge < 2 * P8EST_EDGES); nedge = redge % P8EST_EDGES; nflip = (redge / P8EST_EDGES) ^ iflip; for (j = 0; j < distinct; j++) { if (ntree == etrees[j] && nedge == edges[j] && nflip == edgeorients[j]) { break; } } if (j < distinct) { /* already found from self or faces */ continue; } #if 0 nows[0] = nows[1] = 0; for (i = 0; i < 2; ++i) { if (ntree == ntrees[i]) { /* check if the edge touches this neighbor contact face */ P4EST_ASSERT (fcorners[i][0] >= 0); nfcorners = p8est_edge_face_corners[nedge][nfaces[i]]; if (nfcorners[0] >= 0) { pref = p8est_face_permutation_refs[faces[i]][nfaces[i]]; pset = p8est_face_permutation_sets[pref][orients[i]]; fc[0] = p8est_face_permutations[pset][fcorners[i][0]]; fc[1] = p8est_face_permutations[pset][fcorners[i][1]]; if (fc[0] == nfcorners[nflip] && fc[1] == nfcorners[!nflip]) { P4EST_ASSERT (!founds[i] && !nows[!i]); #ifdef P4EST_ENABLE_DEBUG founds[i] = 1; #endif nows[i] = 1; } else if (fc[0] == nfcorners[!nflip] && fc[1] == nfcorners[nflip]) { ++flipped; } } } } if (nows[0] || nows[1]) { continue; } #endif /* else we have a diagonal edge with ntree */ et = (p8est_edge_transform_t *) sc_array_push (ta); et->ntree = ntree; et->nedge = (int8_t) nedge; et->naxis[0] = (int8_t) (nedge / 4); et->naxis[1] = (int8_t) (nedge < 4 ? 1 : 0); et->naxis[2] = (int8_t) (nedge < 8 ? 2 : 1); et->nflip = (int8_t) nflip; et->corners = (int8_t) (nedge % 4); } return distinct; }