void * p4est_mesh_face_neighbor_data (p4est_mesh_face_neighbor_t * mfn, void *ghost_data) { p4est_locidx_t qtq = mfn->current_qtq; p4est_locidx_t lnq = mfn->mesh->local_num_quadrants; size_t data_size = mfn->p4est->data_size; P4EST_ASSERT (qtq >= 0); if (qtq < lnq) { p4est_topidx_t which_tree; p4est_quadrant_t *q; /* Local quadrant */ which_tree = mfn->which_tree; q = p4est_mesh_quadrant_cumulative (mfn->p4est, qtq, &which_tree, NULL); return q->p.user_data; } else { qtq -= lnq; return (void *) ((char *) ghost_data + data_size * qtq); } }
static void test_mesh (p4est_t * p4est, p4est_ghost_t * ghost, p4est_mesh_t * mesh, int compute_tree_index, int compute_level_lists, p4est_connect_type_t mesh_btype, user_data_t * ghost_data, int uniform) { const int HF = P4EST_HALF * P4EST_FACES; size_t i; int level; int f, nf; int c; int nface; int nrank; p4est_topidx_t which_tree; p4est_locidx_t K, kl; p4est_locidx_t ql, QpG, lnC; p4est_locidx_t qlid, qumid, quadrant_id, which_quad; p4est_mesh_face_neighbor_t mfn, mfn2; p4est_quadrant_t *q; p4est_tree_t *tree; K = mesh->local_num_quadrants; P4EST_ASSERT (K == p4est->local_num_quadrants); QpG = mesh->local_num_quadrants + mesh->ghost_num_quadrants; lnC = mesh->local_num_corners; P4EST_ASSERT (lnC >= 0); P4EST_ASSERT (compute_tree_index == (mesh->quad_to_tree != NULL)); P4EST_ASSERT (compute_level_lists == (mesh->quad_level != NULL)); P4EST_ASSERT ((mesh_btype == P4EST_CONNECT_CORNER) == (mesh->quad_to_corner != NULL)); /* TODO: test the mesh relations in more depth */ tree = NULL; for (kl = 0; kl < K; ++kl) { if (compute_tree_index) { tree = p4est_tree_array_index (p4est->trees, mesh->quad_to_tree[kl]); SC_CHECK_ABORTF (tree->quadrants_offset <= kl && kl < tree->quadrants_offset + (p4est_locidx_t) tree->quadrants.elem_count, "Tree index mismatch %lld", (long long) kl); } if (mesh_btype == P4EST_CONNECT_CORNER) { for (c = 0; c < P4EST_CHILDREN; ++c) { qlid = mesh->quad_to_corner[P4EST_CHILDREN * kl + c]; SC_CHECK_ABORTF (qlid >= -2 && qlid < QpG + lnC, "quad %lld corner %d mismatch", (long long) kl, c); } } for (f = 0; f < P4EST_FACES; ++f) { ql = mesh->quad_to_quad[P4EST_FACES * kl + f]; SC_CHECK_ABORTF (0 <= ql && ql < QpG, "quad %d face %d neighbor %d mismatch", kl, f, ql); nf = mesh->quad_to_face[P4EST_FACES * kl + f]; if (uniform) { SC_CHECK_ABORTF (0 <= nf && nf < HF, "quad %d face %d code %d mismatch", kl, f, nf); } else { SC_CHECK_ABORTF (-HF <= nf && nf < (P4EST_HALF + 1) * HF, "quad %d face %d code %d mismatch", kl, f, nf); } } } /* Test the level lists */ if (compute_tree_index && compute_level_lists) { for (level = 0; level < P4EST_QMAXLEVEL; ++level) { for (i = 0; i < mesh->quad_level[level].elem_count; ++i) { /* get the local quadrant id */ quadrant_id = *(p4est_locidx_t *) sc_array_index (&mesh->quad_level[level], i); /* get the tree it belongs to */ kl = mesh->quad_to_tree[quadrant_id]; tree = p4est_tree_array_index (p4est->trees, kl); /* and finally, get the actual quadrant from the tree quadrant list */ quadrant_id -= tree->quadrants_offset; q = p4est_quadrant_array_index (&tree->quadrants, (size_t) quadrant_id); SC_CHECK_ABORTF (q->level == level, "quad %d level %d mismatch", quadrant_id, level); } } } /* Test face neighbor iterator */ for (qumid = 0; qumid < mesh->local_num_quadrants; ++qumid) { which_tree = -1; q = p4est_mesh_quadrant_cumulative (p4est, qumid, &which_tree, &quadrant_id); p4est_mesh_face_neighbor_init2 (&mfn, p4est, ghost, mesh, which_tree, quadrant_id); p4est_mesh_face_neighbor_init (&mfn2, p4est, ghost, mesh, which_tree, q); P4EST_ASSERT (mfn2.quadrant_id == quadrant_id); while ((q = p4est_mesh_face_neighbor_next (&mfn, &which_tree, &which_quad, &nface, &nrank)) != NULL) { #ifdef P4EST_ENABLE_DEBUG user_data_t *data; data = (user_data_t *) p4est_mesh_face_neighbor_data (&mfn, ghost_data); P4EST_ASSERT (p4est_quadrant_is_equal (q, &(data->quad))); P4EST_ASSERT (data->quad.p.which_tree == which_tree); #endif } } }
p4est_quadrant_t * p4est_mesh_face_neighbor_next (p4est_mesh_face_neighbor_t * mfn, p4est_topidx_t * ntree, p4est_locidx_t * nquad, int *nface, int *nrank) { int qtf; p4est_topidx_t which_tree; p4est_locidx_t qtq, quadfacecode; p4est_locidx_t lnq, *halfs; #ifdef P4EST_ENABLE_DEBUG p4est_locidx_t ngh; #endif p4est_quadrant_t *q; /* We have already processed the last quadrant */ if (mfn->face == P4EST_FACES) { mfn->current_qtq = -1; P4EST_ASSERT (mfn->subface == 0); return NULL; } /* Make sure we have a valid quadrant face and iterator */ lnq = mfn->mesh->local_num_quadrants; #ifdef P4EST_ENABLE_DEBUG ngh = mfn->mesh->ghost_num_quadrants; #endif P4EST_ASSERT (mfn->face >= 0 && mfn->face < P4EST_FACES); P4EST_ASSERT (mfn->subface >= 0 && mfn->subface < P4EST_HALF); P4EST_ASSERT (mfn->p4est->local_num_quadrants == lnq); P4EST_ASSERT (mfn->ghost->ghosts.elem_count == (size_t) ngh); /* Retrieve face and quadrant codes */ quadfacecode = mfn->quadrant_code + (p4est_locidx_t) mfn->face; qtq = mfn->mesh->quad_to_quad[quadfacecode]; qtf = (int) mfn->mesh->quad_to_face[quadfacecode]; if (qtf >= 0) { /* Neighbor is same or double size */ ; /* Advance to next quadrant */ ++mfn->face; } else { /* Neighbors across this face are half size */ P4EST_ASSERT (qtq >= 0); halfs = (p4est_locidx_t *) sc_array_index (mfn->mesh->quad_to_half, (size_t) qtq); qtq = halfs[mfn->subface]; /* Advance to next quadrant */ if (++mfn->subface == P4EST_HALF) { mfn->subface = 0; ++mfn->face; } } mfn->current_qtq = qtq; /* From here on face and subface have advanced and can no longer be used */ P4EST_ASSERT (qtq >= 0); if (qtq < lnq) { /* Local quadrant */ which_tree = mfn->which_tree; q = p4est_mesh_quadrant_cumulative (mfn->p4est, qtq, &which_tree, nquad); if (ntree != NULL) { *ntree = which_tree; } if (nrank != NULL) { *nrank = mfn->p4est->mpirank; } } else { /* Ghost quadrant */ qtq -= lnq; P4EST_ASSERT (qtq < ngh); q = p4est_quadrant_array_index (&mfn->ghost->ghosts, (size_t) qtq); if (ntree != NULL) { *ntree = q->p.piggy3.which_tree; } if (nquad != NULL) { *nquad = qtq; /* number of ghost in the ghost layer */ } if (nrank != NULL) { *nrank = mfn->mesh->ghost_to_proc[qtq]; } } if (nface != NULL) { *nface = qtf; } return q; }