void compare_seeds (sc_array_t * seeds, sc_array_t * seeds_check) { size_t count = seeds->elem_count; size_t zz; p4est_quadrant_t *s, *t; SC_CHECK_ABORT (seeds_check->elem_count == count, "seed count"); for (zz = 0; zz < count; zz++) { s = p4est_quadrant_array_index (seeds, zz); t = p4est_quadrant_array_index (seeds_check, zz); SC_CHECK_ABORT (p4est_quadrant_is_equal (s, t), "seed equality"); } }
void p6est_profile_element_to_node (p6est_t * p6est, p6est_profile_t * profile, p4est_locidx_t * offsets, p4est_locidx_t * elem_to_node, p6est_lnodes_code_t * fc) { p4est_topidx_t jt; p4est_t *columns = p6est->columns; p4est_tree_t *tree; p4est_quadrant_t *col; sc_array_t *tquadrants; p4est_locidx_t (*lr)[2] = (p4est_locidx_t (*)[2]) profile->lnode_ranges; p4est_locidx_t cid; size_t zz; p6est_lnodes_code_t mask = 0x1fe0; p6est_lnodes_code_t hbit = 0x0010; int degree = profile->lnodes->degree; int Nrp = (degree + 1); int Nfp = (degree + 1) * (degree + 1); sc_array_t *layers = p6est->layers; for (cid = 0, jt = columns->first_local_tree; jt <= columns->last_local_tree; ++jt) { tree = p4est_tree_array_index (columns->trees, jt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz, cid++) { p4est_locidx_t nlayers; p4est_locidx_t nid = profile->lnodes->element_nodes[Nfp * cid + Nrp * (Nrp / 2) + (Nrp / 2)]; size_t first, last, zw, zy; col = p4est_quadrant_array_index (tquadrants, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); nlayers = lr[nid][1]; p6est_profile_element_to_node_col (profile, cid, offsets, elem_to_node, fc); elem_to_node += nlayers * (degree + 1) * (degree + 1) * (degree + 1); for (zy = 0, zw = first; zw < last; zw++, zy++) { if (fc[zy] & mask) { /* this layer has vertical half faces, we need to set the bit that * says whether this is the upper half or the lower half */ p2est_quadrant_t *layer; layer = p2est_quadrant_array_index (layers, zw); if (layer->z & P4EST_QUADRANT_LEN (layer->level)) { /* upper half of a pair of layers */ fc[zy] |= hbit; } } } fc += nlayers; } } }
void p4est_wrap_set_coarsen_delay (p4est_wrap_t * pp, int coarsen_delay, int coarsen_affect) { size_t zz; p4est_topidx_t tt; p4est_t *p4est; p4est_tree_t *tree; p4est_quadrant_t *quadrant; sc_array_t *tquadrants; P4EST_ASSERT (pp != NULL); P4EST_ASSERT (coarsen_delay >= 0); pp->coarsen_delay = coarsen_delay; pp->coarsen_affect = coarsen_affect; p4est = pp->p4est; P4EST_ASSERT (p4est->data_size == 0); /* initialize delay memory in the quadrants' user field */ for (tt = p4est->first_local_tree; tt <= p4est->last_local_tree; ++tt) { tree = p4est_tree_array_index (p4est->trees, tt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz) { quadrant = p4est_quadrant_array_index (tquadrants, zz); quadrant->p.user_int = 0; } } }
int p4est_balance_seeds_face (p4est_quadrant_t * q, p4est_quadrant_t * p, int face, p4est_connect_type_t balance, sc_array_t * seeds) { p4est_quadrant_t temp = *p; p4est_quadrant_t *s; int ibalance; int consistent; #ifndef P4_TO_P8 int nextra = 3; p4est_quadrant_t add[3]; #else int nextra = 9; p8est_quadrant_t add[9]; #endif int i; P4EST_ASSERT (seeds == NULL || seeds->elem_size == sizeof (p4est_quadrant_t)); if (balance == P4EST_CONNECT_FULL) { ibalance = P4EST_DIM - 1; } #ifdef P4_TO_P8 else if (balance == P8EST_CONNECT_EDGE) { ibalance = 1; } #endif else { ibalance = 0; } if (seeds == NULL) { p4est_bal_face_con_internal (q, &temp, face, ibalance, &consistent, NULL); return !consistent; } else { memset (add, -1, nextra * sizeof (p4est_quadrant_t)); p4est_bal_face_con_internal (q, &temp, face, ibalance, &consistent, add); sc_array_resize (seeds, 0); if (!consistent) { for (i = 0; i < nextra; i++) { if (add[i].level != -1) { sc_array_resize (seeds, seeds->elem_count + 1); s = p4est_quadrant_array_index (seeds, seeds->elem_count - 1); *s = add[i]; } } } return !consistent; } }
p4est_quadrant_t * p4est_mesh_quadrant_cumulative (p4est_t * p4est, p4est_locidx_t cumulative_id, p4est_topidx_t * which_tree, p4est_locidx_t * quadrant_id) { int the_quadrant_id; p4est_topidx_t low_tree, high_tree, guess_tree; p4est_tree_t *tree; P4EST_ASSERT (0 <= cumulative_id && cumulative_id < p4est->local_num_quadrants); low_tree = p4est->first_local_tree; high_tree = p4est->last_local_tree; if (which_tree != NULL && *which_tree != -1) { guess_tree = *which_tree; } else { guess_tree = (low_tree + high_tree) / 2; } for (;;) { P4EST_ASSERT (p4est->first_local_tree <= low_tree); P4EST_ASSERT (high_tree <= p4est->last_local_tree); P4EST_ASSERT (low_tree <= guess_tree && guess_tree <= high_tree); tree = p4est_tree_array_index (p4est->trees, guess_tree); if (cumulative_id < tree->quadrants_offset) { high_tree = guess_tree - 1; } else if (cumulative_id >= tree->quadrants_offset + (p4est_locidx_t) tree->quadrants.elem_count) { low_tree = guess_tree + 1; } else { the_quadrant_id = cumulative_id - tree->quadrants_offset; P4EST_ASSERT (0 <= the_quadrant_id); if (which_tree != NULL) { *which_tree = guess_tree; } if (quadrant_id != NULL) { *quadrant_id = the_quadrant_id; } return p4est_quadrant_array_index (&tree->quadrants, (size_t) the_quadrant_id); } guess_tree = (low_tree + high_tree) / 2; } }
void standard_seeds (sc_array_t * seeds) { size_t count = seeds->elem_count; size_t zz; p4est_quadrant_t *q, temp; for (zz = 0; zz < count; zz++) { q = p4est_quadrant_array_index (seeds, zz); p4est_quadrant_sibling (q, &temp, 0); *q = temp; } sc_array_sort (seeds, p4est_quadrant_compare); sc_array_uniq (seeds, p4est_quadrant_compare); }
int p4est_balance_seeds_corner (p4est_quadrant_t * q, p4est_quadrant_t * p, int corner, p4est_connect_type_t balance, sc_array_t * seeds) { p4est_quadrant_t temp = *p; p4est_quadrant_t *s; int ibalance; int consistent; P4EST_ASSERT (seeds == NULL || seeds->elem_size == sizeof (p4est_quadrant_t)); if (balance == P4EST_CONNECT_FULL) { ibalance = P4EST_DIM - 1; } #ifdef P4_TO_P8 else if (balance == P8EST_CONNECT_EDGE) { ibalance = 1; } #endif else { ibalance = 0; } p4est_bal_corner_con_internal (q, &temp, corner, ibalance, &consistent); if (seeds == NULL) { return !consistent; } else { sc_array_resize (seeds, 0); if (!consistent) { sc_array_resize (seeds, seeds->elem_count + 1); s = p4est_quadrant_array_index (seeds, seeds->elem_count - 1); *s = temp; } return !consistent; } }
p4est_wrap_leaf_t * p4est_wrap_leaf_first (p4est_wrap_t * pp, int track_mirrors) { p4est_t *p4est = pp->p4est; p4est_wrap_leaf_t *leaf; p4est_quadrant_t *mirror; if (p4est->local_num_quadrants == 0) { P4EST_ASSERT (p4est->first_local_tree == -1); P4EST_ASSERT (p4est->last_local_tree == -2); return NULL; } /* prepare internal state of the leaf iterator */ leaf = P4EST_ALLOC (p4est_wrap_leaf_t, 1); leaf->pp = pp; leaf->which_tree = p4est->first_local_tree; P4EST_ASSERT (leaf->which_tree >= 0); leaf->tree = p4est_tree_array_index (p4est->trees, leaf->which_tree); leaf->tquadrants = &leaf->tree->quadrants; P4EST_ASSERT (leaf->tquadrants->elem_size > 0); leaf->which_quad = 0; /* initialize mirror tracking if desired */ leaf->nm = leaf->next_mirror_quadrant = -1; if (track_mirrors) { leaf->mirrors = &(p4est_wrap_get_ghost (pp))->mirrors; if (leaf->mirrors->elem_count > 0) { mirror = p4est_quadrant_array_index (leaf->mirrors, 0); leaf->next_mirror_quadrant = (int) mirror->p.piggy3.local_num; P4EST_ASSERT (leaf->next_mirror_quadrant >= 0); P4EST_ASSERT (leaf->next_mirror_quadrant < p4est->local_num_quadrants); } } else { leaf->mirrors = NULL; leaf->is_mirror = 0; } /* complete leaf and mirror information */ return p4est_wrap_leaf_info (leaf); }
static void p4est_build_verify_4 (p4est_t * p4est) { p4est_topidx_t jt; p4est_locidx_t il, c1, c2; p4est_tree_t *tree; p4est_quadrant_t *quadrant; test_build_t *tb; tb = (test_build_t *) p4est->user_pointer; c1 = c2 = 0; for (jt = p4est->first_local_tree; jt <= p4est->last_local_tree; ++jt) { tree = p4est_tree_array_index (p4est->trees, jt); for (il = 0; il < (p4est_locidx_t) tree->quadrants.elem_count; ++il) { quadrant = p4est_quadrant_array_index (&tree->quadrants, il); switch (*(long *) quadrant->p.user_data) { case 11321: ++c1; break; case -748: ++c2; break; default: SC_ABORT_NOT_REACHED (); } } } SC_CHECK_ABORT (c1 + c2 == p4est->local_num_quadrants, "Test 4 count quadrants"); SC_CHECK_ABORT (c1 + c2 >= (p4est_locidx_t) tb->count_add, "Test 4 count sum"); SC_CHECK_ABORT (c1 == (p4est_locidx_t) tb->init_default, "Test 4 count default"); SC_CHECK_ABORT (c2 == (p4est_locidx_t) tb->init_add, "Test 4 count add"); }
int main (int argc, char **argv) { sc_MPI_Comm mpicomm; int mpiret; int found_total; p4est_locidx_t jt, Al, Bl; p4est_locidx_t local_count; p4est_connectivity_t *conn; p4est_quadrant_t *A, *B; p4est_geometry_t *geom; p4est_t *p4est; sc_array_t *points; test_point_t *p; const char *vtkname; /* Initialize MPI */ mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); mpicomm = sc_MPI_COMM_WORLD; /* Initialize packages */ sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT); p4est_init (NULL, SC_LP_DEFAULT); /* Create forest */ #ifndef P4_TO_P8 conn = p4est_connectivity_new_star (); geom = NULL; vtkname = "test_search2"; #else conn = p8est_connectivity_new_sphere (); geom = p8est_geometry_new_sphere (conn, 1., 0.191728, 0.039856); vtkname = "test_search3"; #endif p4est = p4est_new_ext (mpicomm, conn, 0, 0, 0, 0, NULL, &local_count); p4est_refine (p4est, 1, refine_fn, NULL); p4est_partition (p4est, 0, NULL); p4est_vtk_write_file (p4est, geom, vtkname); /* The following code should really be in a separate function. */ /* Prepare a point search -- fix size so the memory is not relocated */ points = sc_array_new_size (sizeof (test_point_t), 2); /* A */ p = (test_point_t *) sc_array_index (points, 0); p->name = "A"; A = &p->quad; P4EST_QUADRANT_INIT (A); p4est_quadrant_set_morton (A, 3, 23); A->p.piggy3.which_tree = 0; A->p.piggy3.local_num = -1; Al = -1; /* B */ p = (test_point_t *) sc_array_index (points, 1); p->name = "B"; B = &p->quad; P4EST_QUADRANT_INIT (B); p4est_quadrant_set_morton (B, 2, 13); B->p.piggy3.which_tree = conn->num_trees / 2; B->p.piggy3.local_num = -1; Bl = -1; /* Find quadrant numbers if existing */ for (jt = p4est->first_local_tree; jt <= p4est->last_local_tree; ++jt) { size_t zz; p4est_tree_t *tree = p4est_tree_array_index (p4est->trees, jt); p4est_quadrant_t *quad; sc_array_t *tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz) { quad = p4est_quadrant_array_index (tquadrants, zz); if (A->p.piggy3.which_tree == jt && !p4est_quadrant_compare (quad, A)) { Al = tree->quadrants_offset + (p4est_locidx_t) zz; P4EST_VERBOSEF ("Searching for A at %lld\n", (long long) Al); } if (B->p.piggy3.which_tree == jt && !p4est_quadrant_compare (quad, B)) { Bl = tree->quadrants_offset + (p4est_locidx_t) zz; P4EST_VERBOSEF ("Searching for B at %lld\n", (long long) Bl); } } } /* Go */ found_count = 0; p4est_search_local (p4est, 0, NULL, search_callback, points); mpiret = sc_MPI_Allreduce (&found_count, &found_total, 1, sc_MPI_INT, sc_MPI_SUM, mpicomm); SC_CHECK_MPI (mpiret); SC_CHECK_ABORT (found_total == (int) points->elem_count, "Point search"); SC_CHECK_ABORT (A->p.piggy3.local_num == Al, "Search A"); SC_CHECK_ABORT (B->p.piggy3.local_num == Bl, "Search B"); /* Use another search to count local quadrants */ local_count = 0; p4est_search_local (p4est, 0, count_callback, NULL, NULL); SC_CHECK_ABORT (local_count == p4est->local_num_quadrants, "Count search"); /* Clear memory */ sc_array_destroy (points); p4est_destroy (p4est); if (geom != NULL) { p4est_geometry_destroy (geom); } p4est_connectivity_destroy (conn); /* Test the build_local function and friends */ test_build_local (mpicomm); /* Finalize */ sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
p6est_profile_t * p6est_profile_new_local (p6est_t * p6est, p6est_ghost_t * ghost, p6est_profile_type_t ptype, p8est_connect_type_t btype, int degree) { p6est_profile_t *profile = P4EST_ALLOC (p6est_profile_t, 1); p4est_lnodes_t *lnodes; p4est_locidx_t nln, nle; p4est_topidx_t jt; p4est_t *columns = p6est->columns; p4est_tree_t *tree; sc_array_t *tquadrants; p4est_quadrant_t *col; p4est_qcoord_t diff = P4EST_ROOT_LEN - p6est->root_len; size_t first, last, count, zz, zy; p4est_locidx_t *en, (*lr)[2]; sc_array_t *lc; int i, j; p2est_quadrant_t *layer; sc_array_t *layers = p6est->layers; p4est_locidx_t nidx, enidx; p4est_connect_type_t hbtype; int8_t *c; sc_array_t *thisprof; sc_array_t *selfprof; sc_array_t *faceprof; sc_array_t *cornerprof; sc_array_t *work; sc_array_t oldprof; const int Nrp = degree + 1; P4EST_ASSERT (degree > 1); profile->ptype = ptype; profile->btype = btype; profile->lnode_changed[0] = NULL; profile->lnode_changed[1] = NULL; profile->enode_counts = NULL; profile->diff = diff; if (btype == P8EST_CONNECT_FACE) { hbtype = P4EST_CONNECT_FACE; } else { hbtype = P4EST_CONNECT_FULL; } if (ghost == NULL) { profile->cghost = p4est_ghost_new (p6est->columns, P4EST_CONNECT_FULL); profile->ghost_owned = 1; } else { P4EST_ASSERT (ghost->column_ghost->btype == P4EST_CONNECT_FULL); profile->cghost = ghost->column_ghost; profile->ghost_owned = 0; } if (ptype == P6EST_PROFILE_UNION) { P4EST_ASSERT (degree == 2); } profile->lnodes = lnodes = p4est_lnodes_new (p6est->columns, profile->cghost, degree); en = lnodes->element_nodes; nln = lnodes->num_local_nodes; nle = lnodes->num_local_elements; profile->lnode_ranges = P4EST_ALLOC_ZERO (p4est_locidx_t, 2 * nln); lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges; profile->lnode_columns = lc = sc_array_new (sizeof (int8_t)); selfprof = sc_array_new (sizeof (int8_t)); work = sc_array_new (sizeof (int8_t)); faceprof = sc_array_new (sizeof (int8_t)); cornerprof = sc_array_new (sizeof (int8_t)); if (ptype == P6EST_PROFILE_UNION) { profile->lnode_changed[0] = P4EST_ALLOC (p4est_locidx_t, nln); profile->lnode_changed[1] = P4EST_ALLOC (p4est_locidx_t, nln); profile->enode_counts = P4EST_ALLOC (p4est_locidx_t, P4EST_INSUL * nle); profile->evenodd = 0; memset (profile->lnode_changed[0], -1, nln * sizeof (int)); } /* create the profiles for each node: layers are reduced to just their level * */ for (enidx = 0, jt = columns->first_local_tree; jt <= columns->last_local_tree; ++jt) { tree = p4est_tree_array_index (columns->trees, jt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz) { col = p4est_quadrant_array_index (tquadrants, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); count = last - first; sc_array_truncate (selfprof); c = (int8_t *) sc_array_push_count (selfprof, count); for (zy = first; zy < last; zy++) { layer = p2est_quadrant_array_index (layers, zy); *(c++) = layer->level; } if (ptype == P6EST_PROFILE_UNION) { p6est_profile_balance_self (selfprof, work); if (btype == P8EST_CONNECT_FACE) { p6est_profile_balance_face (selfprof, faceprof, work, diff); } else { p6est_profile_balance_full (selfprof, faceprof, work, diff); } if (btype == P8EST_CONNECT_EDGE) { p6est_profile_balance_face (selfprof, cornerprof, work, diff); } else if (btype == P8EST_CONNECT_FULL) { p6est_profile_balance_full (selfprof, cornerprof, work, diff); } } for (j = 0; j < Nrp; j++) { for (i = 0; i < Nrp; i++, enidx++) { nidx = en[enidx]; if (ptype == P6EST_PROFILE_UNION) { thisprof = NULL; if (!(i % degree) && !(j % degree)) { if (hbtype == P4EST_CONNECT_FACE) { /* skip corners if we don't need to balance them */ P4EST_ASSERT (!lr[nidx][0]); P4EST_ASSERT (!lr[nidx][1]); continue; } else { thisprof = cornerprof; } } else if ((i % degree) && (j % degree)) { thisprof = selfprof; } else { thisprof = faceprof; } count = thisprof->elem_count; profile->enode_counts[enidx] = count; if (!lr[nidx][1]) { /* if this node has not yet been initialized, initialize it */ lr[nidx][0] = lc->elem_count; lr[nidx][1] = count; c = (int8_t *) sc_array_push_count (lc, count); memcpy (c, thisprof->array, count * sizeof (int8_t)); } else { /* if this node has been initialized, combine the two profiles, * taking the finer layers from each */ sc_array_init_view (&oldprof, lc, lr[nidx][0], lr[nidx][1]); p6est_profile_union (thisprof, &oldprof, work); if (work->elem_count > oldprof.elem_count) { lr[nidx][0] = lc->elem_count; lr[nidx][1] = work->elem_count; c = (int8_t *) sc_array_push_count (lc, work->elem_count); memcpy (c, work->array, work->elem_count * work->elem_size); } } } else { count = selfprof->elem_count; if (!lr[nidx][1]) { /* if this node has not yet been initialized, initialize it */ lr[nidx][0] = lc->elem_count; lr[nidx][1] = count; c = (int8_t *) sc_array_push_count (lc, count); memcpy (c, selfprof->array, count * sizeof (int8_t)); } else { /* if this node has been initialized, combine the two profiles, * taking the coarser layers from each */ sc_array_init_view (&oldprof, lc, lr[nidx][0], lr[nidx][1]); p6est_profile_intersection (selfprof, &oldprof, work); P4EST_ASSERT (work->elem_count <= oldprof.elem_count); if (work->elem_count < oldprof.elem_count) { lr[nidx][1] = work->elem_count; memcpy (oldprof.array, work->array, work->elem_count * work->elem_size); } } } } } } } p6est_profile_compress (profile); sc_array_destroy (selfprof); sc_array_destroy (faceprof); sc_array_destroy (cornerprof); sc_array_destroy (work); return profile; }
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 } } }
void p6est_refine_to_profile (p6est_t * p6est, p6est_profile_t * profile, p6est_init_t init_fn, p6est_replace_t replace_fn) { size_t zz, zy, first, last; p4est_topidx_t jt; p4est_quadrant_t *col; p4est_tree_t *tree; sc_array_t *tquadrants; p4est_locidx_t eidx; p4est_locidx_t *en = profile->lnodes->element_nodes; p4est_locidx_t (*lr)[2]; p4est_locidx_t nidx, pidx, pfirst, plast; sc_array_t *layers = p6est->layers; sc_array_t *lc = profile->lnode_columns; sc_array_t *work; P4EST_ASSERT (profile->lnodes->degree == 2); lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges; work = sc_array_new (sizeof (p2est_quadrant_t)); for (eidx = 0, jt = p6est->columns->first_local_tree; jt <= p6est->columns->last_local_tree; ++jt) { tree = p4est_tree_array_index (p6est->columns->trees, jt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz, eidx++) { col = p4est_quadrant_array_index (tquadrants, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); nidx = en[P4EST_INSUL * eidx + P4EST_INSUL / 2]; P4EST_ASSERT ((size_t) lr[nidx][1] >= last - first); pfirst = lr[nidx][0]; plast = pfirst + lr[nidx][1]; if ((size_t) lr[nidx][1] > last - first) { p2est_quadrant_t stack[P4EST_QMAXLEVEL]; p2est_quadrant_t *q, *r, s, t; int stackcount; sc_array_truncate (work); stackcount = 0; zy = first; for (pidx = pfirst; pidx < plast; pidx++) { int8_t p; P4EST_ASSERT (stackcount || zy < last); p = *((int8_t *) sc_array_index (lc, pidx)); if (stackcount) { q = &(stack[--stackcount]); } else { q = p2est_quadrant_array_index (layers, zy++); } P4EST_ASSERT (q->level <= p); while (q->level < p) { p2est_quadrant_t *child[2]; t = *q; s = *q; s.level++; stack[stackcount] = s; stack[stackcount].z += P4EST_QUADRANT_LEN (s.level); child[0] = &s; child[1] = &stack[stackcount++]; p6est_layer_init_data (p6est, jt, col, child[0], init_fn); p6est_layer_init_data (p6est, jt, col, child[1], init_fn); q = &t; if (replace_fn) { replace_fn (p6est, jt, 1, 1, &col, &q, 1, 2, &col, child); } p6est_layer_free_data (p6est, &t); q = &s; } r = p2est_quadrant_array_push (work); *r = *q; } P4EST_ASSERT (work->elem_count == (size_t) lr[nidx][1]); first = layers->elem_count; last = first + work->elem_count; P6EST_COLUMN_SET_RANGE (col, first, last); q = (p2est_quadrant_t *) sc_array_push_count (layers, work->elem_count); memcpy (q, work->array, work->elem_count * work->elem_size); } } } sc_array_destroy (work); p6est_compress_columns (p6est); p6est_update_offsets (p6est); }
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; }
int main (int argc, char **argv) { sc_MPI_Comm mpicomm; int mpiret; int mpisize, mpirank; p4est_t *p4est; p4est_connectivity_t *connectivity; sc_dmatrix_t *vtkvec; p4est_tree_t *tree; sc_array_t *quadrants; size_t zz, count; p4est_quadrant_t *q; int i; #ifndef P4_TO_P8 char filename[] = "p4est_balance_face"; #else char filename[] = "p8est_balance_edge"; #endif p4est_vtk_context_t *context; sc_array_t *level; int retval; /* initialize MPI */ mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); mpicomm = sc_MPI_COMM_WORLD; mpiret = sc_MPI_Comm_size (mpicomm, &mpisize); SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_rank (mpicomm, &mpirank); SC_CHECK_MPI (mpiret); sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT); p4est_init (NULL, SC_LP_DEFAULT); #ifndef P4_TO_P8 connectivity = p4est_connectivity_new_unitsquare (); #else connectivity = p8est_connectivity_new_unitcube (); #endif p4est = p4est_new_ext (mpicomm, connectivity, 0, 2, 1, sizeof (balance_seeds_elem_t), init_fn, NULL); p4est_refine (p4est, 1, refine_fn, init_fn); context = p4est_vtk_context_new (p4est, filename); p4est_vtk_context_set_scale (context, 1. - 2. * SC_EPS); context = p4est_vtk_write_header (context); SC_CHECK_ABORT (context != NULL, P4EST_STRING "_vtk: Error writing header"); vtkvec = sc_dmatrix_new (p4est->local_num_quadrants, P4EST_CHILDREN); tree = p4est_tree_array_index (p4est->trees, 0); quadrants = &(tree->quadrants); count = quadrants->elem_count; for (zz = 0; zz < count; zz++) { q = p4est_quadrant_array_index (quadrants, zz); for (i = 0; i < P4EST_CHILDREN; i++) { vtkvec->e[zz][i] = (double) ((balance_seeds_elem_t *) (q->p.user_data))->flag; } } level = sc_array_new_data ((void *) vtkvec->e[0], sizeof (double), count * P4EST_CHILDREN); context = p4est_vtk_write_point_dataf (context, 1, 0, "level", level, context); SC_CHECK_ABORT (context != NULL, P4EST_STRING "_vtk: Error writing point data"); sc_array_destroy (level); retval = p4est_vtk_write_footer (context); SC_CHECK_ABORT (!retval, P4EST_STRING "_vtk: Error writing footer"); sc_dmatrix_destroy (vtkvec); p4est_destroy (p4est); p4est_connectivity_destroy (connectivity); sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
int p4est_balance_seeds (p4est_quadrant_t * q, p4est_quadrant_t * p, p4est_connect_type_t balance, sc_array_t * seeds) { int outside[P4EST_DIM]; int i; int type = 0; p4est_qcoord_t diff; p4est_qcoord_t qc, pc; p4est_qcoord_t pdist = P4EST_QUADRANT_LEN (p->level); p4est_qcoord_t qdist = P4EST_QUADRANT_LEN (q->level); p4est_quadrant_t *s; int f, c; #ifdef P4_TO_P8 int e; #endif if (seeds != NULL) { sc_array_resize (seeds, 0); } /* basic level comparison */ if (q->level <= p->level + 1) { return 0; } for (i = 0; i < P4EST_DIM; i++) { switch (i) { case 0: qc = q->x; pc = p->x; break; case 1: qc = q->y; pc = p->y; break; #ifdef P4_TO_P8 case 2: qc = q->z; pc = p->z; break; #endif default: SC_ABORT_NOT_REACHED (); break; } outside[i] = 0; if (qc < pc) { diff = pc - qc; /* insulation layer comparison */ if (diff > pdist) { return 0; } outside[i] = -1; } else { diff = (qc + qdist) - (pc + pdist); /* insulation layer comparison */ if (diff > pdist) { return 0; } if (diff > 0) { outside[i] = 1; } } type += (outside[i] ? 1 : 0); } switch (type) { case 0: /* q is inside p, so it is its own seed */ sc_array_resize (seeds, seeds->elem_count + 1); s = p4est_quadrant_array_index (seeds, seeds->elem_count - 1); *s = *q; return 1; case 1: for (i = 0; i < P4EST_DIM; i++) { if (outside[i]) { f = 2 * i + (outside[i] > 0 ? 1 : 0); return p4est_balance_seeds_face (q, p, f, balance, seeds); } } SC_ABORT_NOT_REACHED (); return -1; case P4EST_DIM: c = 0; for (i = 0; i < P4EST_DIM; i++) { c += (outside[i] > 0 ? (1 << i) : 0); } return p4est_balance_seeds_corner (q, p, c, balance, seeds); #ifdef P4_TO_P8 case 2: e = 0; c = 0; for (i = 2; i >= 0; i--) { if (outside[i]) { c <<= 1; c |= (outside[i] > 0 ? 1 : 0); } else { e |= (i << 2); } } e |= c; return p8est_balance_seeds_edge (q, p, e, balance, seeds); #endif default: SC_ABORT_NOT_REACHED (); return -1; } }
static void p4est_coarsen_old (p4est_t * p4est, int coarsen_recursive, p4est_coarsen_t coarsen_fn, p4est_init_t init_fn) { #ifdef P4EST_ENABLE_DEBUG size_t data_pool_size; #endif int i, maxlevel; int couldbegood; size_t zz; size_t incount, removed; size_t cidz, first, last, rest, before; p4est_locidx_t num_quadrants, prev_offset; p4est_topidx_t jt; p4est_tree_t *tree; p4est_quadrant_t *c[P4EST_CHILDREN]; p4est_quadrant_t *cfirst, *clast; sc_array_t *tquadrants; P4EST_GLOBAL_PRODUCTIONF ("Into " P4EST_STRING "_coarsen_old with %lld total quadrants\n", (long long) p4est->global_num_quadrants); p4est_log_indent_push (); P4EST_ASSERT (p4est_is_valid (p4est)); /* loop over all local trees */ prev_offset = 0; for (jt = p4est->first_local_tree; jt <= p4est->last_local_tree; ++jt) { tree = p4est_tree_array_index (p4est->trees, jt); tquadrants = &tree->quadrants; #ifdef P4EST_ENABLE_DEBUG data_pool_size = 0; if (p4est->user_data_pool != NULL) { data_pool_size = p4est->user_data_pool->elem_count; } #endif removed = 0; /* initial log message for this tree */ P4EST_VERBOSEF ("Into coarsen tree %lld with %llu\n", (long long) jt, (unsigned long long) tquadrants->elem_count); /* Initialize array indices. If children are coarsened, the array will have an empty window. first index of the first child to be considered last index of the last child before the hole in the array before number of children before the hole in the array rest index of the first child after the hole in the array */ first = last = 0; before = rest = 1; /* run through the array and coarsen recursively */ incount = tquadrants->elem_count; while (rest + P4EST_CHILDREN - 1 - before < incount) { couldbegood = 1; for (zz = 0; zz < P4EST_CHILDREN; ++zz) { if (zz < before) { c[zz] = p4est_quadrant_array_index (tquadrants, first + zz); if (zz != (size_t) p4est_quadrant_child_id (c[zz])) { couldbegood = 0; break; } } else { c[zz] = p4est_quadrant_array_index (tquadrants, rest + zz - before); } } if (couldbegood && p4est_quadrant_is_familypv (c) && coarsen_fn (p4est, jt, c)) { /* coarsen now */ for (zz = 0; zz < P4EST_CHILDREN; ++zz) { p4est_quadrant_free_data (p4est, c[zz]); } tree->quadrants_per_level[c[0]->level] -= P4EST_CHILDREN; cfirst = c[0]; p4est_quadrant_parent (c[0], cfirst); p4est_quadrant_init_data (p4est, jt, cfirst, init_fn); tree->quadrants_per_level[cfirst->level] += 1; p4est->local_num_quadrants -= P4EST_CHILDREN - 1; removed += P4EST_CHILDREN - 1; rest += P4EST_CHILDREN - before; if (coarsen_recursive) { last = first; cidz = (size_t) p4est_quadrant_child_id (cfirst); if (cidz > first) first = 0; else first -= cidz; } else { /* don't coarsen again, move the counters and the hole */ P4EST_ASSERT (first == last && before == 1); if (rest < incount) { ++first; cfirst = p4est_quadrant_array_index (tquadrants, first); clast = p4est_quadrant_array_index (tquadrants, rest); *cfirst = *clast; last = first; ++rest; } } } else { /* do nothing, just move the counters and the hole */ ++first; if (first > last) { if (first != rest) { cfirst = p4est_quadrant_array_index (tquadrants, first); clast = p4est_quadrant_array_index (tquadrants, rest); *cfirst = *clast; } last = first; ++rest; } } before = last - first + 1; } /* adjust final array size */ first = last; if (first + 1 < rest) { while (rest < incount) { ++first; cfirst = p4est_quadrant_array_index (tquadrants, first); clast = p4est_quadrant_array_index (tquadrants, rest); *cfirst = *clast; ++rest; } sc_array_resize (tquadrants, first + 1); } /* compute maximum level */ maxlevel = 0; num_quadrants = 0; for (i = 0; i <= P4EST_QMAXLEVEL; ++i) { P4EST_ASSERT (tree->quadrants_per_level[i] >= 0); num_quadrants += tree->quadrants_per_level[i]; /* same type */ if (tree->quadrants_per_level[i] > 0) { maxlevel = i; } } tree->maxlevel = (int8_t) maxlevel; tree->quadrants_offset = prev_offset; prev_offset += num_quadrants; /* do some sanity checks */ P4EST_ASSERT (num_quadrants == (p4est_locidx_t) tquadrants->elem_count); P4EST_ASSERT (tquadrants->elem_count == incount - removed); if (p4est->user_data_pool != NULL) { P4EST_ASSERT (data_pool_size - removed == p4est->user_data_pool->elem_count); } P4EST_ASSERT (p4est_tree_is_sorted (tree)); P4EST_ASSERT (p4est_tree_is_complete (tree)); /* final log message for this tree */ P4EST_VERBOSEF ("Done coarsen tree %lld now %llu\n", (long long) jt, (unsigned long long) tquadrants->elem_count); } if (p4est->last_local_tree >= 0) { for (; jt < p4est->connectivity->num_trees; ++jt) { tree = p4est_tree_array_index (p4est->trees, jt); tree->quadrants_offset = p4est->local_num_quadrants; } } /* compute global number of quadrants */ p4est_comm_count_quadrants (p4est); P4EST_ASSERT (p4est_is_valid (p4est)); p4est_log_indent_pop (); P4EST_GLOBAL_PRODUCTIONF ("Done " P4EST_STRING "_coarsen_old with %lld total quadrants\n", (long long) p4est->global_num_quadrants); }
int main (int argc, char **argv) { int rank; int num_procs; int mpiret; sc_MPI_Comm mpicomm; p4est_t *p4est, *copy; p4est_connectivity_t *connectivity; int i; p4est_topidx_t t; size_t qz; p4est_locidx_t num_quadrants_on_last; p4est_locidx_t *num_quadrants_in_proc; p4est_gloidx_t *pertree1, *pertree2; p4est_quadrant_t *quad; p4est_tree_t *tree; user_data_t *user_data; int64_t sum; unsigned crc; mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); mpicomm = sc_MPI_COMM_WORLD; mpiret = sc_MPI_Comm_rank (mpicomm, &rank); SC_CHECK_MPI (mpiret); sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT); /* create connectivity and forest structures */ #ifdef P4_TO_P8 connectivity = p8est_connectivity_new_twocubes (); #else connectivity = p4est_connectivity_new_corner (); #endif p4est = p4est_new_ext (mpicomm, connectivity, 15, 0, 0, sizeof (user_data_t), init_fn, NULL); pertree1 = P4EST_ALLOC (p4est_gloidx_t, p4est->connectivity->num_trees + 1); pertree2 = P4EST_ALLOC (p4est_gloidx_t, p4est->connectivity->num_trees + 1); num_procs = p4est->mpisize; num_quadrants_in_proc = P4EST_ALLOC (p4est_locidx_t, num_procs); /* refine and balance to make the number of elements interesting */ test_pertree (p4est, NULL, pertree1); p4est_refine (p4est, 1, refine_fn, init_fn); test_pertree (p4est, NULL, pertree1); /* Set an arbitrary partition. * * Since this is just a test we assume the global number of * quadrants will fit in an int32_t */ num_quadrants_on_last = (p4est_locidx_t) p4est->global_num_quadrants; for (i = 0; i < num_procs - 1; ++i) { num_quadrants_in_proc[i] = (p4est_locidx_t) i + 1; /* type ok */ num_quadrants_on_last -= (p4est_locidx_t) i + 1; /* type ok */ } num_quadrants_in_proc[num_procs - 1] = num_quadrants_on_last; SC_CHECK_ABORT (num_quadrants_on_last > 0, "Negative number of quadrants on the last processor"); /* Save a checksum of the original forest */ crc = p4est_checksum (p4est); /* partition the forest */ (void) p4est_partition_given (p4est, num_quadrants_in_proc); test_pertree (p4est, pertree1, pertree2); /* Double check that we didn't loose any quads */ SC_CHECK_ABORT (crc == p4est_checksum (p4est), "bad checksum, missing a quad"); /* count the actual number of quadrants per proc */ SC_CHECK_ABORT (num_quadrants_in_proc[rank] == p4est->local_num_quadrants, "partition failed, wrong number of quadrants"); /* check user data content */ for (t = p4est->first_local_tree; t <= p4est->last_local_tree; ++t) { tree = p4est_tree_array_index (p4est->trees, t); for (qz = 0; qz < tree->quadrants.elem_count; ++qz) { quad = p4est_quadrant_array_index (&tree->quadrants, qz); user_data = (user_data_t *) quad->p.user_data; sum = quad->x + quad->y + quad->level; SC_CHECK_ABORT (user_data->a == t, "bad user_data, a"); SC_CHECK_ABORT (user_data->sum == sum, "bad user_data, sum"); } } /* do a weighted partition with uniform weights */ p4est_partition (p4est, 0, weight_one); test_pertree (p4est, pertree1, pertree2); SC_CHECK_ABORT (crc == p4est_checksum (p4est), "bad checksum after uniformly weighted partition"); /* copy the p4est */ copy = p4est_copy (p4est, 1); SC_CHECK_ABORT (crc == p4est_checksum (copy), "bad checksum after copy"); /* do a weighted partition with many zero weights */ weight_counter = 0; weight_index = (rank == 1) ? 1342 : 0; p4est_partition (copy, 0, weight_once); test_pertree (copy, pertree1, pertree2); SC_CHECK_ABORT (crc == p4est_checksum (copy), "bad checksum after unevenly weighted partition 1"); /* do a weighted partition with many zero weights */ weight_counter = 0; weight_index = 0; p4est_partition (copy, 0, weight_once); test_pertree (copy, pertree1, pertree2); SC_CHECK_ABORT (crc == p4est_checksum (copy), "bad checksum after unevenly weighted partition 2"); /* do a weighted partition with many zero weights * * Since this is just a test we assume the local number of * quadrants will fit in an int */ weight_counter = 0; weight_index = (rank == num_procs - 1) ? ((int) copy->local_num_quadrants - 1) : 0; p4est_partition (copy, 0, weight_once); test_pertree (copy, pertree1, pertree2); SC_CHECK_ABORT (crc == p4est_checksum (copy), "bad checksum after unevenly weighted partition 3"); /* check user data content */ for (t = copy->first_local_tree; t <= copy->last_local_tree; ++t) { tree = p4est_tree_array_index (copy->trees, t); for (qz = 0; qz < tree->quadrants.elem_count; ++qz) { quad = p4est_quadrant_array_index (&tree->quadrants, qz); user_data = (user_data_t *) quad->p.user_data; sum = quad->x + quad->y + quad->level; SC_CHECK_ABORT (user_data->a == t, "bad user_data, a"); SC_CHECK_ABORT (user_data->sum == sum, "bad user_data, sum"); } } /* Add another test. Overwrites pertree1, pertree2 */ test_partition_circle (mpicomm, connectivity, pertree1, pertree2); /* clean up and exit */ P4EST_FREE (pertree1); P4EST_FREE (pertree2); P4EST_FREE (num_quadrants_in_proc); p4est_destroy (p4est); p4est_destroy (copy); p4est_connectivity_destroy (connectivity); sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
int main (int argc, char **argv) { const p4est_qcoord_t qone = 1; int mpiret; int k; int level, mid, cid; int id0, id1, id2, id3; int64_t index1, index2; size_t iz, jz, incount; p4est_qcoord_t mh = P4EST_QUADRANT_LEN (P4EST_QMAXLEVEL); p4est_connectivity_t *connectivity; p4est_t *p4est1; p4est_t *p4est2; p4est_tree_t *t1, *t2, tree; p4est_quadrant_t *p, *q1, *q2; p4est_quadrant_t r, s; p4est_quadrant_t c0, c1, c2, c3; p4est_quadrant_t cv[P4EST_CHILDREN], *cp[P4EST_CHILDREN]; p4est_quadrant_t A, B, C, D, E, F, G, H, I, P, Q; p4est_quadrant_t a, f, g, h; uint64_t Aid, Fid; /* initialize MPI */ mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); /* create connectivity and forest structures */ connectivity = p4est_connectivity_new_unitsquare (); p4est1 = p4est_new_ext (sc_MPI_COMM_SELF, connectivity, 15, 0, 0, 0, NULL, NULL); p4est2 = p4est_new_ext (sc_MPI_COMM_SELF, connectivity, 15, 0, 0, 8, NULL, NULL); /* refine the second tree to a uniform level */ p4est_refine (p4est1, 1, refine_none, NULL); p4est_refine (p4est2, 1, refine_some, NULL); t1 = p4est_tree_array_index (p4est1->trees, 0); t2 = p4est_tree_array_index (p4est2->trees, 0); SC_CHECK_ABORT (p4est_tree_is_sorted (t1), "is_sorted"); SC_CHECK_ABORT (p4est_tree_is_sorted (t2), "is_sorted"); /* run a bunch of cross-tests */ p = NULL; for (iz = 0; iz < t1->quadrants.elem_count; ++iz) { q1 = p4est_quadrant_array_index (&t1->quadrants, iz); /* test the index conversion */ index1 = p4est_quadrant_linear_id (q1, (int) q1->level); p4est_quadrant_set_morton (&r, (int) q1->level, index1); index2 = p4est_quadrant_linear_id (&r, (int) r.level); SC_CHECK_ABORT (index1 == index2, "index conversion"); level = (int) q1->level - 1; if (level >= 0) { index1 = p4est_quadrant_linear_id (q1, level); p4est_quadrant_set_morton (&r, level, index1); index2 = p4est_quadrant_linear_id (&r, level); SC_CHECK_ABORT (index1 == index2, "index conversion"); } /* test the is_next function */ if (p != NULL) { SC_CHECK_ABORT (p4est_quadrant_is_next (p, q1), "is_next"); } p = q1; /* test the is_family function */ p4est_quadrant_children (q1, &c0, &c1, &c2, &c3); SC_CHECK_ABORT (p4est_quadrant_is_family (&c0, &c1, &c2, &c3), "is_family"); SC_CHECK_ABORT (!p4est_quadrant_is_family (&c1, &c0, &c2, &c3), "is_family"); SC_CHECK_ABORT (!p4est_quadrant_is_family (&c0, &c0, &c1, &c2), "is_family"); p4est_quadrant_childrenv (q1, cv); SC_CHECK_ABORT (p4est_quadrant_is_equal (&c0, &cv[0]), "is_family"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&c1, &cv[1]), "is_family"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&c2, &cv[2]), "is_family"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&c3, &cv[3]), "is_family"); SC_CHECK_ABORT (p4est_quadrant_is_family (&cv[0], &cv[1], &cv[2], &cv[3]), "is_family"); cp[0] = &cv[0]; cp[1] = &cv[1]; cp[2] = &cv[2]; cp[3] = &cv[3]; SC_CHECK_ABORT (p4est_quadrant_is_familypv (cp), "is_family"); cv[1] = cv[0]; SC_CHECK_ABORT (!p4est_quadrant_is_familyv (cv), "is_family"); cp[1] = &c1; SC_CHECK_ABORT (p4est_quadrant_is_familypv (cp), "is_family"); cp[2] = &c3; SC_CHECK_ABORT (!p4est_quadrant_is_familypv (cp), "is_family"); /* test the sibling function */ mid = p4est_quadrant_child_id (q1); for (cid = 0; cid < 4; ++cid) { p4est_quadrant_sibling (q1, &r, cid); if (cid != mid) { SC_CHECK_ABORT (p4est_quadrant_is_sibling (q1, &r), "sibling"); } else { SC_CHECK_ABORT (p4est_quadrant_is_equal (q1, &r), "sibling"); } } /* test t1 against itself */ for (jz = 0; jz < t1->quadrants.elem_count; ++jz) { q2 = p4est_quadrant_array_index (&t1->quadrants, jz); /* test the comparison function */ SC_CHECK_ABORT (p4est_quadrant_compare (q1, q2) == -p4est_quadrant_compare (q2, q1), "compare"); SC_CHECK_ABORT ((p4est_quadrant_compare (q1, q2) == 0) == p4est_quadrant_is_equal (q1, q2), "is_equal"); /* test the descriptive versions of functions */ SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (q1, q2) == p4est_quadrant_is_sibling (q1, q2), "is_sibling"); SC_CHECK_ABORT (p4est_quadrant_is_parent_D (q1, q2) == p4est_quadrant_is_parent (q1, q2), "is_parent"); SC_CHECK_ABORT (p4est_quadrant_is_parent_D (q2, q1) == p4est_quadrant_is_parent (q2, q1), "is_parent"); SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (q1, q2) == p4est_quadrant_is_ancestor (q1, q2), "is_ancestor"); SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (q2, q1) == p4est_quadrant_is_ancestor (q2, q1), "is_ancestor"); SC_CHECK_ABORT (p4est_quadrant_is_next_D (q1, q2) == p4est_quadrant_is_next (q1, q2), "is_next"); SC_CHECK_ABORT (p4est_quadrant_is_next_D (q2, q1) == p4est_quadrant_is_next (q2, q1), "is_next"); p4est_nearest_common_ancestor_D (q1, q2, &r); p4est_nearest_common_ancestor (q1, q2, &s); SC_CHECK_ABORT (p4est_quadrant_is_equal (&r, &s), "common_ancestor"); p4est_nearest_common_ancestor_D (q2, q1, &r); p4est_nearest_common_ancestor (q2, q1, &s); SC_CHECK_ABORT (p4est_quadrant_is_equal (&r, &s), "common_ancestor"); } /* test t1 against t2 */ for (jz = 0; jz < t2->quadrants.elem_count; ++jz) { q2 = p4est_quadrant_array_index (&t2->quadrants, jz); /* test the comparison function */ SC_CHECK_ABORT (p4est_quadrant_compare (q1, q2) == -p4est_quadrant_compare (q2, q1), "compare"); SC_CHECK_ABORT ((p4est_quadrant_compare (q1, q2) == 0) == p4est_quadrant_is_equal (q1, q2), "is_equal"); /* test the descriptive versions of functions */ SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (q1, q2) == p4est_quadrant_is_sibling (q1, q2), "is_sibling"); SC_CHECK_ABORT (p4est_quadrant_is_parent_D (q1, q2) == p4est_quadrant_is_parent (q1, q2), "is_parent"); SC_CHECK_ABORT (p4est_quadrant_is_parent_D (q2, q1) == p4est_quadrant_is_parent (q2, q1), "is_parent"); SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (q1, q2) == p4est_quadrant_is_ancestor (q1, q2), "is_ancestor"); SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (q2, q1) == p4est_quadrant_is_ancestor (q2, q1), "is_ancestor"); SC_CHECK_ABORT (p4est_quadrant_is_next_D (q1, q2) == p4est_quadrant_is_next (q1, q2), "is_next"); SC_CHECK_ABORT (p4est_quadrant_is_next_D (q2, q1) == p4est_quadrant_is_next (q2, q1), "is_next"); p4est_nearest_common_ancestor_D (q1, q2, &r); p4est_nearest_common_ancestor (q1, q2, &s); SC_CHECK_ABORT (p4est_quadrant_is_equal (&r, &s), "common_ancestor"); p4est_nearest_common_ancestor_D (q2, q1, &r); p4est_nearest_common_ancestor (q2, q1, &s); SC_CHECK_ABORT (p4est_quadrant_is_equal (&r, &s), "common_ancestor"); } } p = NULL; for (iz = 0; iz < t2->quadrants.elem_count; ++iz) { q1 = p4est_quadrant_array_index (&t2->quadrants, iz); /* test the is_next function */ if (p != NULL) { SC_CHECK_ABORT (p4est_quadrant_is_next (p, q1), "is_next"); } p = q1; } /* test the coarsen function */ p4est_coarsen (p4est1, 1, coarsen_none, NULL); p4est_coarsen (p4est1, 1, coarsen_all, NULL); p4est_coarsen (p4est2, 1, coarsen_some, NULL); /* test the linearize algorithm */ incount = t2->quadrants.elem_count; (void) p4est_linearize_tree (p4est2, t2); SC_CHECK_ABORT (incount == t2->quadrants.elem_count, "linearize"); /* this is user_data neutral only when p4est1->data_size == 0 */ sc_array_init (&tree.quadrants, sizeof (p4est_quadrant_t)); sc_array_resize (&tree.quadrants, 18); q1 = p4est_quadrant_array_index (&tree.quadrants, 0); q2 = p4est_quadrant_array_index (&t2->quadrants, 0); *q1 = *q2; q2 = p4est_quadrant_array_index (&t2->quadrants, 1); for (k = 0; k < 3; ++k) { q1 = p4est_quadrant_array_index (&tree.quadrants, (size_t) (k + 1)); *q1 = *q2; q1->level = (int8_t) (q1->level + k); } for (k = 0; k < 10; ++k) { q1 = p4est_quadrant_array_index (&tree.quadrants, (size_t) (k + 4)); q2 = p4est_quadrant_array_index (&t2->quadrants, (size_t) (k + 3)); *q1 = *q2; q1->level = (int8_t) (q1->level + k); } for (k = 0; k < 4; ++k) { q1 = p4est_quadrant_array_index (&tree.quadrants, (size_t) (k + 14)); q2 = p4est_quadrant_array_index (&t2->quadrants, (size_t) (k + 12)); *q1 = *q2; q1->level = (int8_t) (q1->level + 10 + k); } tree.maxlevel = 0; for (k = 0; k <= P4EST_QMAXLEVEL; ++k) { tree.quadrants_per_level[k] = 0; } for (; k <= P4EST_MAXLEVEL; ++k) { tree.quadrants_per_level[k] = -1; } incount = tree.quadrants.elem_count; for (iz = 0; iz < incount; ++iz) { q1 = p4est_quadrant_array_index (&tree.quadrants, iz); ++tree.quadrants_per_level[q1->level]; tree.maxlevel = (int8_t) SC_MAX (tree.maxlevel, q1->level); } SC_CHECK_ABORT (!p4est_tree_is_linear (&tree), "is_linear"); (void) p4est_linearize_tree (p4est1, &tree); SC_CHECK_ABORT (incount - 3 == tree.quadrants.elem_count, "linearize"); sc_array_reset (&tree.quadrants); /* create a partial tree and check overlap */ sc_array_resize (&tree.quadrants, 3); q1 = p4est_quadrant_array_index (&tree.quadrants, 0); p4est_quadrant_set_morton (q1, 1, 1); q1 = p4est_quadrant_array_index (&tree.quadrants, 1); p4est_quadrant_set_morton (q1, 2, 8); q1 = p4est_quadrant_array_index (&tree.quadrants, 2); p4est_quadrant_set_morton (q1, 2, 9); for (k = 0; k <= P4EST_QMAXLEVEL; ++k) { tree.quadrants_per_level[k] = 0; } for (; k <= P4EST_MAXLEVEL; ++k) { tree.quadrants_per_level[k] = -1; } tree.quadrants_per_level[1] = 1; tree.quadrants_per_level[2] = 2; tree.maxlevel = 2; p4est_quadrant_first_descendant (p4est_quadrant_array_index (&tree.quadrants, 0), &tree.first_desc, P4EST_QMAXLEVEL); p4est_quadrant_last_descendant (p4est_quadrant_array_index (&tree.quadrants, tree.quadrants.elem_count - 1), &tree.last_desc, P4EST_QMAXLEVEL); SC_CHECK_ABORT (p4est_tree_is_complete (&tree), "is_complete"); p4est_quadrant_set_morton (&D, 0, 0); SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &D), "overlaps 0"); p4est_quadrant_set_morton (&A, 1, 0); SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &A), "overlaps 1"); p4est_quadrant_set_morton (&A, 1, 1); SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &A), "overlaps 2"); p4est_quadrant_set_morton (&A, 1, 2); SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &A), "overlaps 3"); p4est_quadrant_set_morton (&A, 1, 3); SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &A), "overlaps 4"); p4est_quadrant_set_morton (&B, 3, 13); SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &B), "overlaps 5"); p4est_quadrant_set_morton (&B, 3, 25); SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &B), "overlaps 6"); p4est_quadrant_set_morton (&B, 3, 39); SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &B), "overlaps 7"); p4est_quadrant_set_morton (&B, 3, 40); SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &B), "overlaps 8"); p4est_quadrant_set_morton (&C, 4, 219); SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &C), "overlaps 9"); sc_array_reset (&tree.quadrants); /* destroy the p4est and its connectivity structure */ p4est_destroy (p4est1); p4est_destroy (p4est2); p4est_connectivity_destroy (connectivity); /* This will test the ability to address negative quadrants */ P4EST_QUADRANT_INIT (&A); P4EST_QUADRANT_INIT (&B); P4EST_QUADRANT_INIT (&C); P4EST_QUADRANT_INIT (&D); P4EST_QUADRANT_INIT (&E); P4EST_QUADRANT_INIT (&F); P4EST_QUADRANT_INIT (&G); P4EST_QUADRANT_INIT (&H); P4EST_QUADRANT_INIT (&I); P4EST_QUADRANT_INIT (&P); P4EST_QUADRANT_INIT (&Q); A.x = -qone << P4EST_MAXLEVEL; A.y = -qone << P4EST_MAXLEVEL; A.level = 0; B.x = qone << P4EST_MAXLEVEL; B.y = -qone << P4EST_MAXLEVEL; B.level = 0; C.x = -qone << P4EST_MAXLEVEL; C.y = qone << P4EST_MAXLEVEL; C.level = 0; D.x = qone << P4EST_MAXLEVEL; D.y = qone << P4EST_MAXLEVEL; D.level = 0; /* this one is outside the 3x3 box */ E.x = -qone << (P4EST_MAXLEVEL + 1); E.y = -qone; E.level = 0; F.x = P4EST_ROOT_LEN + (P4EST_ROOT_LEN - mh); F.y = P4EST_ROOT_LEN + (P4EST_ROOT_LEN - mh); F.level = P4EST_QMAXLEVEL; G.x = -mh; G.y = -mh; G.level = P4EST_QMAXLEVEL; H.x = -qone << (P4EST_MAXLEVEL - 1); H.y = -qone << (P4EST_MAXLEVEL - 1); H.level = 1; I.x = -qone << P4EST_MAXLEVEL; I.y = -qone << (P4EST_MAXLEVEL - 1); I.level = 1; check_linear_id (&A, &A); check_linear_id (&A, &B); check_linear_id (&A, &C); check_linear_id (&A, &D); /* check_linear_id (&A, &E); */ check_linear_id (&A, &F); check_linear_id (&A, &G); check_linear_id (&A, &H); check_linear_id (&A, &I); check_linear_id (&B, &A); check_linear_id (&B, &B); check_linear_id (&B, &C); check_linear_id (&B, &D); /* check_linear_id (&B, &E); */ check_linear_id (&B, &F); check_linear_id (&B, &G); check_linear_id (&B, &H); check_linear_id (&B, &I); check_linear_id (&D, &A); check_linear_id (&D, &B); check_linear_id (&D, &C); check_linear_id (&D, &D); /* check_linear_id (&D, &E); */ check_linear_id (&D, &F); check_linear_id (&D, &G); check_linear_id (&D, &H); check_linear_id (&D, &I); check_linear_id (&G, &A); check_linear_id (&G, &B); check_linear_id (&G, &C); check_linear_id (&G, &D); /* check_linear_id (&G, &E); */ check_linear_id (&G, &F); check_linear_id (&G, &G); check_linear_id (&G, &H); check_linear_id (&G, &I); check_linear_id (&I, &A); check_linear_id (&I, &B); check_linear_id (&I, &C); check_linear_id (&I, &D); /* check_linear_id (&I, &E); */ check_linear_id (&I, &F); check_linear_id (&I, &G); check_linear_id (&I, &H); check_linear_id (&I, &I); SC_CHECK_ABORT (p4est_quadrant_is_extended (&A) == 1, "is_extended A"); SC_CHECK_ABORT (p4est_quadrant_is_extended (&B) == 1, "is_extended B"); SC_CHECK_ABORT (p4est_quadrant_is_extended (&C) == 1, "is_extended C"); SC_CHECK_ABORT (p4est_quadrant_is_extended (&D) == 1, "is_extended D"); SC_CHECK_ABORT (!p4est_quadrant_is_extended (&E) == 1, "!is_extended E"); SC_CHECK_ABORT (p4est_quadrant_is_extended (&F) == 1, "is_extended F"); SC_CHECK_ABORT (p4est_quadrant_is_extended (&G) == 1, "is_extended G"); SC_CHECK_ABORT (p4est_quadrant_compare (&A, &A) == 0, "compare"); SC_CHECK_ABORT (p4est_quadrant_compare (&A, &B) > 0, "compare"); SC_CHECK_ABORT (p4est_quadrant_compare (&B, &A) < 0, "compare"); SC_CHECK_ABORT (p4est_quadrant_compare (&F, &F) == 0, "compare"); SC_CHECK_ABORT (p4est_quadrant_compare (&G, &F) > 0, "compare"); SC_CHECK_ABORT (p4est_quadrant_compare (&F, &G) < 0, "compare"); A.p.which_tree = 0; B.p.piggy1.which_tree = 0; SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&A, &A) == 0, "compare_piggy"); SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&A, &B) > 0, "compare_piggy"); SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&B, &A) < 0, "compare_piggy"); F.p.piggy2.which_tree = 0; G.p.which_tree = 0; SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&F, &F) == 0, "compare_piggy"); SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&G, &F) > 0, "compare_piggy"); SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&F, &G) < 0, "compare_piggy"); F.p.piggy1.which_tree = (p4est_topidx_t) P4EST_TOPIDX_MAX - 3; G.p.piggy2.which_tree = (p4est_topidx_t) P4EST_TOPIDX_MAX / 2; SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&F, &F) == 0, "compare_piggy"); SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&G, &F) < 0, "compare_piggy"); SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&F, &G) > 0, "compare_piggy"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &A) == 1, "is_equal"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&F, &F) == 1, "is_equal"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&G, &G) == 1, "is_equal"); /* Not sure if these make sense because D, O and A are all level 0 */ #if 0 SC_CHECK_ABORT (p4est_quadrant_is_sibling (&D, &O) == 1, "is_sibling"); SC_CHECK_ABORT (p4est_quadrant_is_sibling (&D, &A) == 0, "is_sibling"); SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (&D, &O) == 1, "is_sibling_D"); SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (&D, &A) == 0, "is_sibling_D"); #endif SC_CHECK_ABORT (p4est_quadrant_is_sibling (&I, &H) == 1, "is_sibling"); SC_CHECK_ABORT (p4est_quadrant_is_sibling (&I, &G) == 0, "is_sibling"); SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (&I, &H) == 1, "is_sibling_D"); SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (&I, &G) == 0, "is_sibling_D"); SC_CHECK_ABORT (p4est_quadrant_is_parent (&A, &H) == 1, "is_parent"); SC_CHECK_ABORT (p4est_quadrant_is_parent (&H, &A) == 0, "is_parent"); SC_CHECK_ABORT (p4est_quadrant_is_parent (&A, &D) == 0, "is_parent"); SC_CHECK_ABORT (p4est_quadrant_is_parent_D (&A, &H) == 1, "is_parent_D"); SC_CHECK_ABORT (p4est_quadrant_is_ancestor (&A, &G) == 1, "is_ancestor"); SC_CHECK_ABORT (p4est_quadrant_is_ancestor (&G, &A) == 0, "is_ancestor"); SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (&A, &G) == 1, "is_ancestor_D"); SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (&G, &A) == 0, "is_ancestor_D"); /* SC_CHECK_ABORT (p4est_quadrant_is_next (&F, &E) == 1, "is_next"); */ SC_CHECK_ABORT (p4est_quadrant_is_next (&A, &H) == 0, "is_next"); /* SC_CHECK_ABORT (p4est_quadrant_is_next_D (&F, &E) == 1, "is_next_D"); */ SC_CHECK_ABORT (p4est_quadrant_is_next_D (&A, &H) == 0, "is_next_D"); p4est_quadrant_parent (&H, &a); SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &a) == 1, "parent"); p4est_quadrant_sibling (&I, &h, 3); SC_CHECK_ABORT (p4est_quadrant_is_equal (&H, &h) == 1, "sibling"); p4est_quadrant_children (&A, &c0, &c1, &c2, &c3); SC_CHECK_ABORT (p4est_quadrant_is_equal (&c2, &I) == 1, "children"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&c3, &H) == 1, "children"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&c3, &G) == 0, "children"); SC_CHECK_ABORT (p4est_quadrant_is_family (&c0, &c1, &c2, &c3) == 1, "is_family"); id0 = p4est_quadrant_child_id (&c0); id1 = p4est_quadrant_child_id (&c1); id2 = p4est_quadrant_child_id (&c2); id3 = p4est_quadrant_child_id (&c3); SC_CHECK_ABORT (id0 == 0 && id1 == 1 && id2 == 2 && id3 == 3, "child_id"); SC_CHECK_ABORT (p4est_quadrant_child_id (&G) == 3, "child_id"); p4est_quadrant_first_descendant (&A, &c1, 1); SC_CHECK_ABORT (p4est_quadrant_is_equal (&c0, &c1) == 1, "first_descendant"); p4est_quadrant_last_descendant (&A, &g, P4EST_QMAXLEVEL); SC_CHECK_ABORT (p4est_quadrant_is_equal (&G, &g) == 1, "last_descendant"); Fid = p4est_quadrant_linear_id (&F, P4EST_QMAXLEVEL); p4est_quadrant_set_morton (&f, P4EST_QMAXLEVEL, Fid); SC_CHECK_ABORT (p4est_quadrant_is_equal (&F, &f) == 1, "set_morton/linear_id"); Aid = p4est_quadrant_linear_id (&A, 0); p4est_quadrant_set_morton (&a, 0, Aid); SC_CHECK_ABORT (Aid == 15, "linear_id"); SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &a) == 1, "set_morton/linear_id"); p4est_nearest_common_ancestor (&I, &H, &a); SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &a) == 1, "ancestor"); p4est_nearest_common_ancestor_D (&I, &H, &a); SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &a) == 1, "ancestor_D"); for (k = 0; k < 16; ++k) { if (k != 4 && k != 6 && k != 8 && k != 9 && k != 12 && k != 13 && k != 14) { p4est_quadrant_set_morton (&E, 0, (uint64_t) k); } } p4est_quadrant_set_morton (&P, 0, 10); p4est_quadrant_set_morton (&Q, 0, 11); SC_CHECK_ABORT (p4est_quadrant_is_next (&P, &Q), "is_next"); SC_CHECK_ABORT (!p4est_quadrant_is_next (&A, &Q), "is_next"); sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
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); }
static void p4est_check_local_order (p4est_t * p4est, p4est_connectivity_t * connectivity) { const double intsize = 1.0 / P4EST_ROOT_LEN; double *vertices; double h, eta1, eta2; double v0x, v0y, v0z, v1x, v1y, v1z; double v2x, v2y, v2z, v3x, v3y, v3z; double w0x, w0y, w0z, w1x, w1y, w1z; double w2x, w2y, w2z, w3x, w3y, w3z; size_t iz; size_t num_quads; size_t quad_count; p4est_topidx_t jt; p4est_topidx_t *tree_to_vertex; p4est_topidx_t first_local_tree; p4est_topidx_t last_local_tree; p4est_topidx_t v0, v1, v2, v3; p4est_locidx_t kl; p4est_locidx_t lv0, lv1, lv2, lv3; p4est_locidx_t num_uniq_local_vertices; p4est_locidx_t *quadrant_to_local_vertex; p4est_qcoord_t inth; p4est_tree_t *tree; p4est_quadrant_t *quad; p4est_vert_t *vert_locations; p4est_nodes_t *nodes; sc_array_t *trees; sc_array_t *quadrants; nodes = p4est_nodes_new (p4est, NULL); quadrant_to_local_vertex = nodes->local_nodes; num_uniq_local_vertices = nodes->num_owned_indeps; SC_CHECK_ABORT ((size_t) num_uniq_local_vertices == nodes->indep_nodes.elem_count, "Node count mismatch"); P4EST_INFOF ("Unique local vertices %lld\n", (long long) num_uniq_local_vertices); vert_locations = P4EST_ALLOC (p4est_vert_t, num_uniq_local_vertices); for (kl = 0; kl < num_uniq_local_vertices; ++kl) { vert_locations[kl].treeid = -1; } tree_to_vertex = connectivity->tree_to_vertex; vertices = connectivity->vertices; first_local_tree = p4est->first_local_tree; last_local_tree = p4est->last_local_tree; trees = p4est->trees; for (jt = first_local_tree, quad_count = 0; jt <= last_local_tree; ++jt) { tree = p4est_tree_array_index (trees, jt); P4EST_ASSERT (0 <= jt && jt < connectivity->num_trees); v0 = tree_to_vertex[jt * 4 + 0]; v1 = tree_to_vertex[jt * 4 + 1]; v2 = tree_to_vertex[jt * 4 + 2]; v3 = tree_to_vertex[jt * 4 + 3]; P4EST_ASSERT (0 <= v0 && v0 < connectivity->num_vertices); P4EST_ASSERT (0 <= v1 && v1 < connectivity->num_vertices); P4EST_ASSERT (0 <= v2 && v2 < connectivity->num_vertices); P4EST_ASSERT (0 <= v3 && v3 < connectivity->num_vertices); v0x = vertices[v0 * 3 + 0]; v0y = vertices[v0 * 3 + 1]; v0z = vertices[v0 * 3 + 2]; v1x = vertices[v1 * 3 + 0]; v1y = vertices[v1 * 3 + 1]; v1z = vertices[v1 * 3 + 2]; v2x = vertices[v2 * 3 + 0]; v2y = vertices[v2 * 3 + 1]; v2z = vertices[v2 * 3 + 2]; v3x = vertices[v3 * 3 + 0]; v3y = vertices[v3 * 3 + 1]; v3z = vertices[v3 * 3 + 2]; quadrants = &tree->quadrants; num_quads = quadrants->elem_count; /* loop over the elements in the tree */ for (iz = 0; iz < num_quads; ++iz, ++quad_count) { quad = p4est_quadrant_array_index (quadrants, iz); inth = P4EST_QUADRANT_LEN (quad->level); h = intsize * inth; eta1 = intsize * quad->x; eta2 = intsize * quad->y; w0x = v0x * (1.0 - eta1) * (1.0 - eta2) + v1x * (eta1) * (1.0 - eta2) + v2x * (1.0 - eta1) * (eta2) + v3x * (eta1) * (eta2); w0y = v0y * (1.0 - eta1) * (1.0 - eta2) + v1y * (eta1) * (1.0 - eta2) + v2y * (1.0 - eta1) * (eta2) + v3y * (eta1) * (eta2); w0z = v0z * (1.0 - eta1) * (1.0 - eta2) + v1z * (eta1) * (1.0 - eta2) + v2z * (1.0 - eta1) * (eta2) + v3z * (eta1) * (eta2); w1x = v0x * (1.0 - eta1 - h) * (1.0 - eta2) + v1x * (eta1 + h) * (1.0 - eta2) + v2x * (1.0 - eta1 - h) * (eta2) + v3x * (eta1 + h) * (eta2); w1y = v0y * (1.0 - eta1 - h) * (1.0 - eta2) + v1y * (eta1 + h) * (1.0 - eta2) + v2y * (1.0 - eta1 - h) * (eta2) + v3y * (eta1 + h) * (eta2); w1z = v0z * (1.0 - eta1 - h) * (1.0 - eta2) + v1z * (eta1 + h) * (1.0 - eta2) + v2z * (1.0 - eta1 - h) * (eta2) + v3z * (eta1 + h) * (eta2); w2x = v0x * (1.0 - eta1) * (1.0 - eta2 - h) + v1x * (eta1) * (1.0 - eta2 - h) + v2x * (1.0 - eta1) * (eta2 + h) + v3x * (eta1) * (eta2 + h); w2y = v0y * (1.0 - eta1) * (1.0 - eta2 - h) + v1y * (eta1) * (1.0 - eta2 - h) + v2y * (1.0 - eta1) * (eta2 + h) + v3y * (eta1) * (eta2 + h); w2z = v0z * (1.0 - eta1) * (1.0 - eta2 - h) + v1z * (eta1) * (1.0 - eta2 - h) + v2z * (1.0 - eta1) * (eta2 + h) + v3z * (eta1) * (eta2 + h); w3x = v0x * (1.0 - eta1 - h) * (1.0 - eta2 - h) + v1x * (eta1 + h) * (1.0 - eta2 - h) + v2x * (1.0 - eta1 - h) * (eta2 + h) + v3x * (eta1 + h) * (eta2 + h); w3y = v0y * (1.0 - eta1 - h) * (1.0 - eta2 - h) + v1y * (eta1 + h) * (1.0 - eta2 - h) + v2y * (1.0 - eta1 - h) * (eta2 + h) + v3y * (eta1 + h) * (eta2 + h); w3z = v0z * (1.0 - eta1 - h) * (1.0 - eta2 - h) + v1z * (eta1 + h) * (1.0 - eta2 - h) + v2z * (1.0 - eta1 - h) * (eta2 + h) + v3z * (eta1 + h) * (eta2 + h); P4EST_ASSERT ((p4est_locidx_t) quad_count < p4est->local_num_quadrants); lv0 = quadrant_to_local_vertex[4 * quad_count + 0]; lv1 = quadrant_to_local_vertex[4 * quad_count + 1]; lv2 = quadrant_to_local_vertex[4 * quad_count + 2]; lv3 = quadrant_to_local_vertex[4 * quad_count + 3]; P4EST_ASSERT (0 <= lv0 && lv0 < num_uniq_local_vertices); P4EST_ASSERT (0 <= lv1 && lv1 < num_uniq_local_vertices); P4EST_ASSERT (0 <= lv2 && lv2 < num_uniq_local_vertices); P4EST_ASSERT (0 <= lv3 && lv3 < num_uniq_local_vertices); vert_locations[lv0].x = w0x; vert_locations[lv0].y = w0y; vert_locations[lv0].z = w0z; P4EST_ASSERT (vert_locations[lv0].treeid == -1 || vert_locations[lv0].treeid == jt); vert_locations[lv0].treeid = jt; vert_locations[lv1].x = w1x; vert_locations[lv1].y = w1y; vert_locations[lv1].z = w1z; P4EST_ASSERT (vert_locations[lv1].treeid == -1 || vert_locations[lv1].treeid == jt); vert_locations[lv1].treeid = jt; vert_locations[lv2].x = w2x; vert_locations[lv2].y = w2y; vert_locations[lv2].z = w2z; P4EST_ASSERT (vert_locations[lv2].treeid == -1 || vert_locations[lv2].treeid == jt); vert_locations[lv2].treeid = jt; vert_locations[lv3].x = w3x; vert_locations[lv3].y = w3y; vert_locations[lv3].z = w3z; P4EST_ASSERT (vert_locations[lv3].treeid == -1 || vert_locations[lv3].treeid == jt); vert_locations[lv3].treeid = jt; } } qsort (vert_locations, num_uniq_local_vertices, sizeof (p4est_vert_t), p4est_vert_compare); /* Check to make sure that we don't have any duplicates in the list */ for (kl = 0; kl < num_uniq_local_vertices - 1; ++kl) { SC_CHECK_ABORT (p4est_vert_compare (vert_locations + kl, vert_locations + kl + 1) != 0, "local ordering not unique"); } P4EST_FREE (vert_locations); p4est_nodes_destroy (nodes); }
trilinear_mesh_t * p8est_trilinear_mesh_new_from_nodes (p4est_t * p4est, p4est_nodes_t * nodes) { const int num_procs = p4est->mpisize; const int rank = p4est->mpirank; int mpiret; int k, owner; #ifdef P4EST_DEBUG int prev_owner = 0; int64_t prev_fvnid = -1; #endif int *sharers; size_t current, zz, num_sharers; int32_t e, n, local_owned_end; int64_t global_borrowed, global_shared; int64_t local_counts[5], global_counts[5]; int32link_t *lynk, **tail; p4est_topidx_t which_tree; p4est_locidx_t *local_node, *shared_offsets; p4est_tree_t *tree; p4est_quadrant_t *q; p4est_indep_t *in; p8est_hang4_t *fh; p8est_hang2_t *eh; trilinear_elem_t *elem; trilinear_anode_t *anode; trilinear_dnode_t *dnode; trilinear_mesh_t *mesh; trilinear_mesh_pid_t *elem_pids; trilinear_mesh_pid_t *node_pids; sc_recycle_array_t *rarr; P4EST_GLOBAL_PRODUCTIONF ("Into trilinear_mesh_extract with %lld total elements\n", (long long) p4est->global_num_quadrants); /* Allocate output data structure. */ mesh = P4EST_ALLOC_ZERO (trilinear_mesh_t, 1); memset (mesh, -1, sizeof (*mesh)); shared_offsets = nodes->shared_offsets; /* Assign local counts. */ P4EST_ASSERT (nodes->num_local_quadrants == p4est->local_num_quadrants); mesh->local_elem_num = p4est->local_num_quadrants; mesh->local_anode_num = nodes->indep_nodes.elem_count; mesh->local_dnode_num = nodes->face_hangings.elem_count + nodes->edge_hangings.elem_count; mesh->local_onode_num = nodes->num_owned_indeps; mesh->local_owned_offset = nodes->offset_owned_indeps; mesh->local_node_num = mesh->local_anode_num + mesh->local_dnode_num; local_owned_end = mesh->local_owned_offset + mesh->local_onode_num; /* Communicate global counts. */ local_counts[0] = mesh->local_elem_num; local_counts[1] = mesh->local_anode_num; local_counts[2] = mesh->local_onode_num; local_counts[3] = mesh->local_dnode_num; local_counts[4] = nodes->num_owned_shared; mpiret = MPI_Allreduce (local_counts, global_counts, 5, MPI_LONG_LONG_INT, MPI_SUM, p4est->mpicomm); SC_CHECK_MPI (mpiret); P4EST_ASSERT (global_counts[0] == p4est->global_num_quadrants); mesh->total_elem_num = global_counts[0]; global_borrowed = global_counts[1] - global_counts[2]; mesh->total_anode_num = global_counts[2]; mesh->total_dnode_num = global_counts[3]; global_shared = global_counts[4]; mesh->total_node_num = mesh->total_anode_num + mesh->total_dnode_num; /* Allocate the mesh memory. */ mesh->elem_table = P4EST_ALLOC (trilinear_elem_t, mesh->local_elem_num); mesh->node_table = P4EST_ALLOC (trilinear_node_t, mesh->local_node_num); mesh->fvnid_count_table = P4EST_ALLOC (int64_t, num_procs + 1); mesh->fvnid_interval_table = P4EST_ALLOC (int64_t, num_procs + 1); mesh->all_fvnid_start = mesh->fvnid_interval_table; mesh->sharer_pool = sc_mempool_new (sizeof (int32link_t)); mesh->elem_pids = P4EST_ALLOC (trilinear_mesh_pid_t, mesh->local_node_num); mesh->node_pids = P4EST_ALLOC (trilinear_mesh_pid_t, mesh->local_node_num); /* Assign global free variable information. */ mesh->fvnid_interval_table[0] = 0; for (k = 0; k < num_procs; ++k) { mesh->fvnid_interval_table[k + 1] = mesh->fvnid_interval_table[k] + (mesh->fvnid_count_table[k] = nodes->global_owned_indeps[k]); } mesh->fvnid_count_table[num_procs] = -1; mesh->global_fvnid_num = mesh->fvnid_interval_table[num_procs]; mesh->global_fvnid_start = 0; mesh->global_fvnid_end = mesh->global_fvnid_num - 1; P4EST_ASSERT (mesh->global_fvnid_num == mesh->total_anode_num); /* Assign element information. */ local_node = nodes->local_nodes; which_tree = p4est->first_local_tree; elem_pids = mesh->elem_pids; if (which_tree >= 0) { tree = p4est_tree_array_index (p4est->trees, which_tree); current = 0; for (e = 0; e < mesh->local_elem_num; ++e) { if (current == tree->quadrants.elem_count) { ++which_tree; tree = p4est_tree_array_index (p4est->trees, which_tree); current = 0; } q = p4est_quadrant_array_index (&tree->quadrants, current); elem = mesh->elem_table + e; for (k = 0; k < P4EST_CHILDREN; ++k) { elem->local_node_id[k] = *local_node++; } elem->lx = (tick_t) q->x; elem->ly = (tick_t) q->y; elem->lz = (tick_t) q->z; elem->size = P4EST_QUADRANT_LEN (q->level); elem->data = q->p.user_data; elem_pids[e] = (trilinear_mesh_pid_t) which_tree; ++current; } P4EST_ASSERT (which_tree == p4est->last_local_tree); P4EST_ASSERT (current == tree->quadrants.elem_count); } /* Assign anchored node information. */ mesh->anode_table = mesh->node_table; mesh->onode_table = mesh->node_table + mesh->local_owned_offset; mesh->dnode_table = mesh->node_table + mesh->local_anode_num; node_pids = mesh->node_pids; for (n = 0; n < mesh->local_anode_num; ++n) { anode = &mesh->node_table[n].anchored; in = (p4est_indep_t *) sc_array_index (&nodes->indep_nodes, (size_t) n); anode->point.x = in->x; anode->point.y = in->y; anode->point.z = in->z; node_pids[n] = (trilinear_mesh_pid_t) in->p.piggy3.which_tree; if (n < mesh->local_owned_offset) { owner = nodes->nonlocal_ranks[n]; P4EST_ASSERT (owner < rank && owner >= prev_owner); } else if (n >= local_owned_end) { owner = nodes->nonlocal_ranks[n - mesh->local_onode_num]; P4EST_ASSERT (owner > rank && owner >= prev_owner); } else { owner = rank; } anode->fvnid = mesh->all_fvnid_start[owner] + in->p.piggy3.local_num; P4EST_ASSERT (anode->fvnid > prev_fvnid); if (in->pad8 == 0) { P4EST_ASSERT (in->pad16 == -1); P4EST_ASSERT (shared_offsets == NULL || shared_offsets[n] == -1); anode->share = NULL; } else { P4EST_ASSERT (in->pad8 > 0); num_sharers = (size_t) in->pad8; rarr = (sc_recycle_array_t *) sc_array_index (&nodes->shared_indeps, num_sharers - 1); if (nodes->shared_offsets == NULL) { P4EST_ASSERT (in->pad16 >= 0); zz = (size_t) in->pad16; } else { P4EST_ASSERT (in->pad16 == -1); zz = (size_t) shared_offsets[n]; } sharers = (int *) sc_array_index (&rarr->a, zz); tail = &anode->share; for (zz = 0; zz < num_sharers; ++zz) { *tail = lynk = (int32link_t *) sc_mempool_alloc (mesh->sharer_pool); lynk->id = (int32_t) sharers[zz]; tail = &lynk->next; } *tail = NULL; } #ifdef P4EST_DEBUG prev_owner = owner; prev_fvnid = anode->fvnid; #endif } /* Assign face hanging node information. */ for (zz = 0; zz < nodes->face_hangings.elem_count; ++n, ++zz) { dnode = &mesh->node_table[n].dangling; fh = (p8est_hang4_t *) sc_array_index (&nodes->face_hangings, zz); dnode->point.x = fh->x; dnode->point.y = fh->y; dnode->point.z = fh->z; dnode->type = 0; /* Not used in Rhea. */ dnode->local_anode_id[0] = fh->p.piggy.depends[0]; dnode->local_anode_id[1] = fh->p.piggy.depends[1]; dnode->local_anode_id[2] = fh->p.piggy.depends[2]; dnode->local_anode_id[3] = fh->p.piggy.depends[3]; node_pids[n] = (trilinear_mesh_pid_t) fh->p.piggy.which_tree; } /* Assign edge hanging node information. */ for (zz = 0; zz < nodes->edge_hangings.elem_count; ++n, ++zz) { dnode = &mesh->node_table[n].dangling; eh = (p8est_hang2_t *) sc_array_index (&nodes->edge_hangings, zz); dnode->point.x = eh->x; dnode->point.y = eh->y; dnode->point.z = eh->z; dnode->type = 0; /* Not used in Rhea. */ dnode->local_anode_id[0] = eh->p.piggy.depends[0]; dnode->local_anode_id[1] = eh->p.piggy.depends[1]; dnode->local_anode_id[2] = dnode->local_anode_id[3] = -1; node_pids[n] = (trilinear_mesh_pid_t) eh->p.piggy.which_tree; } P4EST_ASSERT (n == mesh->local_node_num); /* Assign the remaining variables. */ mesh->mpicomm = p4est->mpicomm; mesh->mpisize = (int32_t) num_procs; mesh->mpirank = (int32_t) rank; mesh->recsize = (int32_t) p4est->data_size; mesh->destructor = p8est_trilinear_mesh_destroy; /* These members are incomplete and need to be filled later. */ memset (mesh->bounds, 0, 6 * sizeof (int)); memset (mesh->sizes, 0, 3 * sizeof (int)); mesh->minsize = mesh->maxsize = 0; mesh->ticksize = 0.; mesh->extra_info = NULL; mesh->gid = -1; /* We are done */ P4EST_GLOBAL_PRODUCTIONF ("Done trilinear_mesh_extract" " with %lld anodes %lld %lld\n", (long long) mesh->total_anode_num, (long long) global_borrowed, (long long) global_shared); return mesh; }
int p6est_vtk_write_header (p6est_t * p6est, double scale, int write_tree, int write_rank, int wrap_rank, const char *point_scalars, const char *point_vectors, const char *filename) { p6est_connectivity_t *connectivity = p6est->connectivity; p4est_t *p4est = p6est->columns; sc_array_t *layers = p6est->layers; sc_array_t *trees = p4est->trees; const int mpirank = p4est->mpirank; const double intsize = 1.0 / P4EST_ROOT_LEN; double v[24]; const p4est_topidx_t first_local_tree = p4est->first_local_tree; const p4est_topidx_t last_local_tree = p4est->last_local_tree; const p4est_locidx_t Ncells = (p4est_locidx_t) layers->elem_count; const p4est_locidx_t Ncorners = P8EST_CHILDREN * Ncells; #ifdef P4EST_VTK_ASCII double wx, wy, wz; p4est_locidx_t sk; #else int retval; uint8_t *uint8_data; p4est_locidx_t *locidx_data; #endif int xi, yi, j, k; int zi; double h2, h2z, eta_x, eta_y, eta_z = 0.; double xyz[3]; /* 3 not P4EST_DIM */ size_t num_cols, zz, zy, first, last; p4est_topidx_t jt; p4est_locidx_t quad_count, Ntotal; p4est_locidx_t il; P4EST_VTK_FLOAT_TYPE *float_data; sc_array_t *columns; p4est_tree_t *tree; p4est_quadrant_t *col; p2est_quadrant_t *layer; char vtufilename[BUFSIZ]; FILE *vtufile; SC_CHECK_ABORT (connectivity->conn4->num_vertices > 0, "Must provide connectivity with vertex information"); P4EST_ASSERT (0. <= scale && scale <= 1. && wrap_rank >= 0); Ntotal = Ncorners; if (scale == 1.) { scale = 1. - 2. * SC_EPS; P4EST_ASSERT (scale < 1.); } /* Have each proc write to its own file */ snprintf (vtufilename, BUFSIZ, "%s_%04d.vtu", filename, mpirank); /* Use "w" for writing the initial part of the file. * For further parts, use "r+" and fseek so write_compressed succeeds. */ vtufile = fopen (vtufilename, "wb"); if (vtufile == NULL) { P4EST_LERRORF ("Could not open %s for output\n", vtufilename); return -1; } fprintf (vtufile, "<?xml version=\"1.0\"?>\n"); fprintf (vtufile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\""); #if defined P4EST_VTK_BINARY && defined P4EST_VTK_COMPRESSION fprintf (vtufile, " compressor=\"vtkZLibDataCompressor\""); #endif #ifdef SC_IS_BIGENDIAN fprintf (vtufile, " byte_order=\"BigEndian\">\n"); #else fprintf (vtufile, " byte_order=\"LittleEndian\">\n"); #endif fprintf (vtufile, " <UnstructuredGrid>\n"); fprintf (vtufile, " <Piece NumberOfPoints=\"%lld\" NumberOfCells=\"%lld\">\n", (long long) Ntotal, (long long) Ncells); fprintf (vtufile, " <Points>\n"); float_data = P4EST_ALLOC (P4EST_VTK_FLOAT_TYPE, 3 * Ntotal); /* write point position data */ fprintf (vtufile, " <DataArray type=\"%s\" Name=\"Position\"" " NumberOfComponents=\"3\" format=\"%s\">\n", P4EST_VTK_FLOAT_NAME, P4EST_VTK_FORMAT_STRING); /* loop over the trees */ for (jt = first_local_tree, quad_count = 0; jt <= last_local_tree; ++jt) { tree = p4est_tree_array_index (trees, jt); columns = &tree->quadrants; num_cols = columns->elem_count; p6est_tree_get_vertices (connectivity, jt, v); /* loop over the elements in tree and calculated vertex coordinates */ for (zz = 0; zz < num_cols; ++zz) { col = p4est_quadrant_array_index (columns, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); for (zy = first; zy < last; zy++, quad_count++) { layer = p2est_quadrant_array_index (layers, zy); h2 = .5 * intsize * P4EST_QUADRANT_LEN (col->level); h2z = .5 * intsize * P4EST_QUADRANT_LEN (layer->level); k = 0; for (zi = 0; zi < 2; ++zi) { for (yi = 0; yi < 2; ++yi) { for (xi = 0; xi < 2; ++xi) { P4EST_ASSERT (0 <= k && k < P8EST_CHILDREN); eta_x = intsize * col->x + h2 * (1. + (xi * 2 - 1) * scale); eta_y = intsize * col->y + h2 * (1. + (yi * 2 - 1) * scale); eta_z = intsize * layer->z + h2z * (1. + (zi * 2 - 1) * scale); for (j = 0; j < 3; ++j) { /* *INDENT-OFF* */ xyz[j] = ((1. - eta_z) * ((1. - eta_y) * ((1. - eta_x) * v[3 * 0 + j] + eta_x * v[3 * 1 + j]) + eta_y * ((1. - eta_x) * v[3 * 2 + j] + eta_x * v[3 * 3 + j])) + eta_z * ((1. - eta_y) * ((1. - eta_x) * v[3 * 4 + j] + eta_x * v[3 * 5 + j]) + eta_y * ((1. - eta_x) * v[3 * 6 + j] + eta_x * v[3 * 7 + j])) ); /* *INDENT-ON* */ } for (j = 0; j < 3; ++j) { float_data[3 * (P8EST_CHILDREN * quad_count + k) + j] = (P4EST_VTK_FLOAT_TYPE) xyz[j]; } ++k; } } } P4EST_ASSERT (k == P8EST_CHILDREN); } } } P4EST_ASSERT (P8EST_CHILDREN * quad_count == Ntotal); #ifdef P4EST_VTK_ASCII for (il = 0; il < Ntotal; ++il) { wx = float_data[3 * il + 0]; wy = float_data[3 * il + 1]; wz = float_data[3 * il + 2]; #ifdef P4EST_VTK_DOUBLES fprintf (vtufile, " %24.16e %24.16e %24.16e\n", wx, wy, wz); #else fprintf (vtufile, " %16.8e %16.8e %16.8e\n", wx, wy, wz); #endif } #else fprintf (vtufile, " "); /* TODO: Don't allocate the full size of the array, only allocate * the chunk that will be passed to zlib and do this a chunk * at a time. */ retval = p6est_vtk_write_binary (vtufile, (char *) float_data, sizeof (*float_data) * 3 * Ntotal); fprintf (vtufile, "\n"); if (retval) { P4EST_LERROR ("p6est_vtk: Error encoding points\n"); fclose (vtufile); return -1; } #endif P4EST_FREE (float_data); fprintf (vtufile, " </DataArray>\n"); fprintf (vtufile, " </Points>\n"); fprintf (vtufile, " <Cells>\n"); /* write connectivity data */ fprintf (vtufile, " <DataArray type=\"%s\" Name=\"connectivity\"" " format=\"%s\">\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING); #ifdef P4EST_VTK_ASCII for (sk = 0, il = 0; il < Ncells; ++il) { fprintf (vtufile, " "); for (k = 0; k < P8EST_CHILDREN; ++sk, ++k) { fprintf (vtufile, " %lld", (long long) sk); } fprintf (vtufile, "\n"); } #else locidx_data = P4EST_ALLOC (p4est_locidx_t, Ncorners); fprintf (vtufile, " "); for (il = 0; il < Ncorners; ++il) { locidx_data[il] = il; } retval = p6est_vtk_write_binary (vtufile, (char *) locidx_data, sizeof (*locidx_data) * Ncorners); fprintf (vtufile, "\n"); if (retval) { P4EST_LERROR ("p6est_vtk: Error encoding connectivity\n"); fclose (vtufile); return -1; } #endif fprintf (vtufile, " </DataArray>\n"); /* write offset data */ fprintf (vtufile, " <DataArray type=\"%s\" Name=\"offsets\"" " format=\"%s\">\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING); #ifdef P4EST_VTK_ASCII fprintf (vtufile, " "); for (il = 1, sk = 1; il <= Ncells; ++il, ++sk) { fprintf (vtufile, " %lld", (long long) (P8EST_CHILDREN * il)); if (!(sk % 8) && il != Ncells) fprintf (vtufile, "\n "); } fprintf (vtufile, "\n"); #else for (il = 1; il <= Ncells; ++il) locidx_data[il - 1] = P8EST_CHILDREN * il; /* same type */ fprintf (vtufile, " "); retval = p6est_vtk_write_binary (vtufile, (char *) locidx_data, sizeof (*locidx_data) * Ncells); fprintf (vtufile, "\n"); if (retval) { P4EST_LERROR ("p6est_vtk: Error encoding offsets\n"); fclose (vtufile); return -1; } #endif fprintf (vtufile, " </DataArray>\n"); /* write type data */ fprintf (vtufile, " <DataArray type=\"UInt8\" Name=\"types\"" " format=\"%s\">\n", P4EST_VTK_FORMAT_STRING); #ifdef P4EST_VTK_ASCII fprintf (vtufile, " "); for (il = 0, sk = 1; il < Ncells; ++il, ++sk) { fprintf (vtufile, " %d", P4EST_VTK_CELL_TYPE); if (!(sk % 20) && il != (Ncells - 1)) fprintf (vtufile, "\n "); } fprintf (vtufile, "\n"); #else uint8_data = P4EST_ALLOC (uint8_t, Ncells); for (il = 0; il < Ncells; ++il) uint8_data[il] = P4EST_VTK_CELL_TYPE; fprintf (vtufile, " "); retval = p6est_vtk_write_binary (vtufile, (char *) uint8_data, sizeof (*uint8_data) * Ncells); P4EST_FREE (uint8_data); fprintf (vtufile, "\n"); if (retval) { P4EST_LERROR ("p6est_vtk: Error encoding types\n"); fclose (vtufile); return -1; } #endif fprintf (vtufile, " </DataArray>\n"); fprintf (vtufile, " </Cells>\n"); if (write_rank || write_tree) { fprintf (vtufile, " <CellData Scalars=\"%s\">\n", !write_tree ? "mpirank" : !write_rank ? "treeid" : "mpirank,treeid"); } if (write_rank) { const int wrapped_rank = wrap_rank > 0 ? mpirank % wrap_rank : mpirank; fprintf (vtufile, " <DataArray type=\"%s\" Name=\"mpirank\"" " format=\"%s\">\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING); #ifdef P4EST_VTK_ASCII fprintf (vtufile, " "); for (il = 0, sk = 1; il < Ncells; ++il, ++sk) { fprintf (vtufile, " %d", wrapped_rank); if (!(sk % 20) && il != (Ncells - 1)) fprintf (vtufile, "\n "); } fprintf (vtufile, "\n"); #else for (il = 0; il < Ncells; ++il) locidx_data[il] = (p4est_locidx_t) wrapped_rank; fprintf (vtufile, " "); retval = p6est_vtk_write_binary (vtufile, (char *) locidx_data, sizeof (*locidx_data) * Ncells); fprintf (vtufile, "\n"); if (retval) { P4EST_LERROR ("p6est_vtk: Error encoding types\n"); fclose (vtufile); return -1; } #endif fprintf (vtufile, " </DataArray>\n"); } if (write_tree) { fprintf (vtufile, " <DataArray type=\"%s\" Name=\"treeid\"" " format=\"%s\">\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING); #ifdef P4EST_VTK_ASCII fprintf (vtufile, " "); for (il = 0, sk = 1, jt = first_local_tree; jt <= last_local_tree; ++jt) { tree = p4est_tree_array_index (trees, jt); num_cols = tree->quadrants.elem_count; columns = &tree->quadrants; for (zz = 0; zz < num_cols; ++zz) { col = p4est_quadrant_array_index (columns, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); for (zy = first; zy < last; zy++, sk++, il++) { fprintf (vtufile, " %lld", (long long) jt); if (!(sk % 20) && il != (Ncells - 1)) fprintf (vtufile, "\n "); } } } fprintf (vtufile, "\n"); #else for (il = 0, jt = first_local_tree; jt <= last_local_tree; ++jt) { tree = p4est_tree_array_index (trees, jt); num_cols = tree->quadrants.elem_count; columns = &tree->quadrants; for (zz = 0; zz < num_cols; ++zz) { col = p4est_quadrant_array_index (columns, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); for (zy = first; zy < last; zy++, il++) { locidx_data[il] = (p4est_locidx_t) jt; } } } fprintf (vtufile, " "); retval = p6est_vtk_write_binary (vtufile, (char *) locidx_data, sizeof (*locidx_data) * Ncells); fprintf (vtufile, "\n"); if (retval) { P4EST_LERROR ("p6est_vtk: Error encoding types\n"); fclose (vtufile); return -1; } #endif fprintf (vtufile, " </DataArray>\n"); P4EST_ASSERT (il == Ncells); } if (write_rank || write_tree) { fprintf (vtufile, " </CellData>\n"); } #ifndef P4EST_VTK_ASCII P4EST_FREE (locidx_data); #endif fprintf (vtufile, " <PointData"); if (point_scalars != NULL) fprintf (vtufile, " Scalars=\"%s\"", point_scalars); if (point_vectors != NULL) fprintf (vtufile, " Vectors=\"%s\"", point_vectors); fprintf (vtufile, ">\n"); if (ferror (vtufile)) { P4EST_LERROR ("p6est_vtk: Error writing header\n"); fclose (vtufile); return -1; } if (fclose (vtufile)) { P4EST_LERROR ("p6est_vtk: Error closing header\n"); return -1; } vtufile = NULL; /* Only have the root write to the parallel vtk file */ if (mpirank == 0) { char pvtufilename[BUFSIZ]; FILE *pvtufile; snprintf (pvtufilename, BUFSIZ, "%s.pvtu", filename); pvtufile = fopen (pvtufilename, "wb"); if (!pvtufile) { P4EST_LERRORF ("Could not open %s for output\n", vtufilename); return -1; } fprintf (pvtufile, "<?xml version=\"1.0\"?>\n"); fprintf (pvtufile, "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\""); #if defined P4EST_VTK_BINARY && defined P4EST_VTK_COMPRESSION fprintf (pvtufile, " compressor=\"vtkZLibDataCompressor\""); #endif #ifdef SC_IS_BIGENDIAN fprintf (pvtufile, " byte_order=\"BigEndian\">\n"); #else fprintf (pvtufile, " byte_order=\"LittleEndian\">\n"); #endif fprintf (pvtufile, " <PUnstructuredGrid GhostLevel=\"0\">\n"); fprintf (pvtufile, " <PPoints>\n"); fprintf (pvtufile, " <PDataArray type=\"%s\" Name=\"Position\"" " NumberOfComponents=\"3\" format=\"%s\"/>\n", P4EST_VTK_FLOAT_NAME, P4EST_VTK_FORMAT_STRING); fprintf (pvtufile, " </PPoints>\n"); if (write_rank || write_tree) { fprintf (pvtufile, " <PCellData Scalars=\"%s\">\n", !write_tree ? "mpirank" : !write_rank ? "treeid" : "mpirank,treeid"); } if (write_rank) { fprintf (pvtufile, " " "<PDataArray type=\"%s\" Name=\"mpirank\" format=\"%s\"/>\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING); } if (write_tree) { fprintf (pvtufile, " " "<PDataArray type=\"%s\" Name=\"treeid\" format=\"%s\"/>\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING); } if (write_rank || write_tree) { fprintf (pvtufile, " </PCellData>\n"); } fprintf (pvtufile, " <PPointData>\n"); if (ferror (pvtufile)) { P4EST_LERROR ("p6est_vtk: Error writing parallel header\n"); fclose (pvtufile); return -1; } if (fclose (pvtufile)) { P4EST_LERROR ("p6est_vtk: Error closing parallel header\n"); return -1; } } return 0; }
p4est_gloidx_t * p6est_lnodes_get_column_labels (p6est_t * p6est, p8est_lnodes_t * lnodes) { p4est_gloidx_t *labels; p4est_gloidx_t num_cols = 0; p4est_gloidx_t global_num_cols = 0; p4est_topidx_t jt; p4est_tree_t *tree; sc_array_t *tquadrants; p4est_quadrant_t *col; size_t zz, first, last; p4est_locidx_t lfirst, llast, lk; int stride = lnodes->degree + 1; int vnodes = lnodes->vnodes; int mpiret, i; labels = P4EST_ALLOC (p4est_gloidx_t, lnodes->owned_count); memset (labels, -1, lnodes->owned_count * sizeof (*labels)); for (jt = p6est->columns->first_local_tree; jt <= p6est->columns->last_local_tree; ++jt) { tree = p4est_tree_array_index (p6est->columns->trees, jt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz) { col = p4est_quadrant_array_index (tquadrants, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); lfirst = (p4est_locidx_t) first; llast = (p4est_locidx_t) last; for (i = 0; i < vnodes; i += stride) { p4est_locidx_t fnid = lnodes->element_nodes[vnodes * lfirst + i]; p4est_locidx_t lnid = lnodes->element_nodes[vnodes * (llast - 1) + i + (stride - 1)]; P4EST_ASSERT (lnid >= 0); P4EST_ASSERT (lnid >= fnid); P4EST_ASSERT (fnid < lnodes->num_local_nodes); if (lnid < lnodes->owned_count) { P4EST_ASSERT (fnid < lnodes->owned_count); if (labels[fnid] < 0) { for (lk = fnid; lk <= lnid; lk++) { labels[lk] = num_cols; } num_cols++; } } } } } mpiret = sc_MPI_Exscan (&num_cols, &global_num_cols, 1, P4EST_MPI_GLOIDX, sc_MPI_SUM, lnodes->mpicomm); SC_CHECK_MPI (mpiret); if (!p6est->mpirank) { global_num_cols = 0; } for (lk = 0; lk < lnodes->owned_count; lk++) { labels[lk] += global_num_cols; } #if 0 { sc_array_t view; sc_array_init_data (&view, labels, sizeof (*labels), (size_t) lnodes->num_local_nodes); p6est_lnodes_share_owned (&view, lnodes); } #endif for (lk = 0; lk < lnodes->owned_count; lk++) { P4EST_ASSERT (labels[lk] >= 0); } return labels; }
p4est_t * p4est_new_points (sc_MPI_Comm mpicomm, p4est_connectivity_t * connectivity, int maxlevel, p4est_quadrant_t * points, p4est_locidx_t num_points, p4est_locidx_t max_points, size_t data_size, p4est_init_t init_fn, void *user_pointer) { int mpiret; int num_procs, rank; int i, isizet; size_t lcount; size_t *nmemb; #ifdef P4EST_ENABLE_DEBUG size_t zz; #endif p4est_topidx_t jt, num_trees; p4est_topidx_t first_tree, last_tree, next_tree; p4est_quadrant_t *first_quad, *next_quad, *quad; p4est_quadrant_t a, b, c, f, l, n; p4est_tree_t *tree; p4est_t *p4est; p4est_points_state_t ppstate; P4EST_GLOBAL_PRODUCTIONF ("Into " P4EST_STRING "_new_points with max level %d max points %lld\n", maxlevel, (long long) max_points); p4est_log_indent_push (); P4EST_ASSERT (p4est_connectivity_is_valid (connectivity)); P4EST_ASSERT (max_points >= -1); /* retrieve MPI information */ mpiret = sc_MPI_Comm_size (mpicomm, &num_procs); SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_rank (mpicomm, &rank); SC_CHECK_MPI (mpiret); /* This implementation runs in O(P/p * maxlevel) * with P the total number of points, p the number of processors. * Two optimizations are possible: * 1. At startup remove points that lead to duplicate quadrants. * 2. Use complete_region between successive points instead of * the call to refine. This should give O(N/p) * maxlevel * with N the total number of quadrants. */ /* parallel sort the incoming points */ lcount = (size_t) num_points; nmemb = P4EST_ALLOC_ZERO (size_t, num_procs); isizet = (int) sizeof (size_t); mpiret = sc_MPI_Allgather (&lcount, isizet, sc_MPI_BYTE, nmemb, isizet, sc_MPI_BYTE, mpicomm); SC_CHECK_MPI (mpiret); sc_psort (mpicomm, points, nmemb, sizeof (p4est_quadrant_t), p4est_quadrant_compare_piggy); P4EST_FREE (nmemb); #ifdef P4EST_ENABLE_DEBUG first_quad = points; for (zz = 1; zz < lcount; ++zz) { next_quad = points + zz; P4EST_ASSERT (p4est_quadrant_compare_piggy (first_quad, next_quad) <= 0); first_quad = next_quad; } #endif /* create the p4est */ p4est = P4EST_ALLOC_ZERO (p4est_t, 1); ppstate.points = points; ppstate.num_points = num_points; ppstate.max_points = max_points; ppstate.current = 0; ppstate.maxlevel = maxlevel; /* assign some data members */ p4est->data_size = 2 * sizeof (p4est_locidx_t); /* temporary */ p4est->user_pointer = &ppstate; p4est->connectivity = connectivity; num_trees = connectivity->num_trees; /* create parallel environment */ p4est_comm_parallel_env_create (p4est, mpicomm); /* allocate memory pools */ p4est->user_data_pool = sc_mempool_new (p4est->data_size); p4est->quadrant_pool = sc_mempool_new (sizeof (p4est_quadrant_t)); P4EST_GLOBAL_PRODUCTIONF ("New " P4EST_STRING " with %lld trees on %d processors\n", (long long) num_trees, num_procs); /* allocate trees */ p4est->trees = sc_array_new (sizeof (p4est_tree_t)); sc_array_resize (p4est->trees, num_trees); for (jt = 0; jt < num_trees; ++jt) { tree = p4est_tree_array_index (p4est->trees, jt); sc_array_init (&tree->quadrants, sizeof (p4est_quadrant_t)); P4EST_QUADRANT_INIT (&tree->first_desc); P4EST_QUADRANT_INIT (&tree->last_desc); tree->quadrants_offset = 0; for (i = 0; i <= P4EST_QMAXLEVEL; ++i) { tree->quadrants_per_level[i] = 0; } for (; i <= P4EST_MAXLEVEL; ++i) { tree->quadrants_per_level[i] = -1; } tree->maxlevel = 0; } p4est->local_num_quadrants = 0; p4est->global_num_quadrants = 0; /* create point based partition */ P4EST_QUADRANT_INIT (&f); p4est->global_first_position = P4EST_ALLOC_ZERO (p4est_quadrant_t, num_procs + 1); if (num_points == 0) { P4EST_VERBOSE ("Empty processor"); first_tree = p4est->first_local_tree = -1; first_quad = NULL; } else { /* we are probably not empty */ if (rank == 0) { first_tree = p4est->first_local_tree = 0; p4est_quadrant_set_morton (&f, maxlevel, 0); } else { first_tree = p4est->first_local_tree = points->p.which_tree; p4est_node_to_quadrant (points, maxlevel, &f); } first_quad = &f; } last_tree = p4est->last_local_tree = -2; p4est_comm_global_partition (p4est, first_quad); first_quad = p4est->global_first_position + rank; next_quad = p4est->global_first_position + (rank + 1); next_tree = next_quad->p.which_tree; if (first_tree >= 0 && p4est_quadrant_is_equal (first_quad, next_quad) && first_quad->p.which_tree == next_quad->p.which_tree) { /* if all our points are consumed by the next processor we are empty */ first_tree = p4est->first_local_tree = -1; } if (first_tree >= 0) { /* we are definitely not empty */ if (next_quad->x == 0 && next_quad->y == 0 #ifdef P4_TO_P8 && next_quad->z == 0 #endif ) { last_tree = p4est->last_local_tree = next_tree - 1; } else { last_tree = p4est->last_local_tree = next_tree; } P4EST_ASSERT (first_tree <= last_tree); } /* fill the local trees */ P4EST_QUADRANT_INIT (&a); P4EST_QUADRANT_INIT (&b); P4EST_QUADRANT_INIT (&c); P4EST_QUADRANT_INIT (&l); n = *next_quad; n.level = (int8_t) maxlevel; for (jt = first_tree; jt <= last_tree; ++jt) { int onlyone = 0; int includeb = 0; tree = p4est_tree_array_index (p4est->trees, jt); /* determine first local quadrant of this tree */ if (jt == first_tree) { a = *first_quad; a.level = (int8_t) maxlevel; first_quad = next_quad = NULL; /* free to use further down */ P4EST_ASSERT (p4est_quadrant_is_valid (&a)); } else { p4est_quadrant_set_morton (&a, maxlevel, 0); P4EST_ASSERT (jt < next_tree || p4est_quadrant_compare (&a, &n) < 0); } /* enlarge first local quadrant if possible */ if (jt < next_tree) { while (p4est_quadrant_child_id (&a) == 0 && a.level > 0) { p4est_quadrant_parent (&a, &a); } P4EST_ASSERT (jt == first_tree || a.level == 0); } else { for (c = a; p4est_quadrant_child_id (&c) == 0; a = c) { p4est_quadrant_parent (&c, &c); p4est_quadrant_last_descendant (&c, &l, maxlevel); if (p4est_quadrant_compare (&l, &n) >= 0) { break; } } P4EST_ASSERT (a.level > 0); P4EST_ASSERT ((p4est_quadrant_last_descendant (&a, &l, maxlevel), p4est_quadrant_compare (&l, &n) < 0)); } p4est_quadrant_first_descendant (&a, &tree->first_desc, P4EST_QMAXLEVEL); /* determine largest possible last quadrant of this tree */ if (jt < next_tree) { p4est_quadrant_last_descendant (&a, &l, maxlevel); p4est_quadrant_set_morton (&b, 0, 0); p4est_quadrant_last_descendant (&b, &b, maxlevel); if (p4est_quadrant_is_equal (&l, &b)) { onlyone = 1; } else { includeb = 1; for (c = b; p4est_quadrant_child_id (&c) == P4EST_CHILDREN - 1; b = c) { p4est_quadrant_parent (&c, &c); p4est_quadrant_first_descendant (&c, &f, maxlevel); if (p4est_quadrant_compare (&l, &f) >= 0) { break; } } } } else { b = n; } /* create a complete tree */ if (onlyone) { quad = p4est_quadrant_array_push (&tree->quadrants); *quad = a; p4est_quadrant_init_data (p4est, jt, quad, p4est_points_init); tree->maxlevel = a.level; ++tree->quadrants_per_level[a.level]; } else { p4est_complete_region (p4est, &a, 1, &b, includeb, tree, jt, p4est_points_init); quad = p4est_quadrant_array_index (&tree->quadrants, tree->quadrants.elem_count - 1); } tree->quadrants_offset = p4est->local_num_quadrants; p4est->local_num_quadrants += tree->quadrants.elem_count; p4est_quadrant_last_descendant (quad, &tree->last_desc, P4EST_QMAXLEVEL); /* verification */ #ifdef P4EST_ENABLE_DEBUG first_quad = p4est_quadrant_array_index (&tree->quadrants, 0); for (zz = 1; zz < tree->quadrants.elem_count; ++zz) { next_quad = p4est_quadrant_array_index (&tree->quadrants, zz); P4EST_ASSERT (((p4est_locidx_t *) first_quad->p.user_data)[1] == ((p4est_locidx_t *) next_quad->p.user_data)[0]); first_quad = next_quad; } #endif } if (last_tree >= 0) { for (; jt < num_trees; ++jt) { tree = p4est_tree_array_index (p4est->trees, jt); tree->quadrants_offset = p4est->local_num_quadrants; } } /* compute some member variables */ p4est->global_first_quadrant = P4EST_ALLOC (p4est_gloidx_t, num_procs + 1); p4est_comm_count_quadrants (p4est); /* print more statistics */ P4EST_VERBOSEF ("total local quadrants %lld\n", (long long) p4est->local_num_quadrants); P4EST_ASSERT (p4est_is_valid (p4est)); p4est_log_indent_pop (); P4EST_GLOBAL_PRODUCTIONF ("Done " P4EST_STRING "_new_points with %lld total quadrants\n", (long long) p4est->global_num_quadrants); /* refine to have one point per quadrant */ if (max_points >= 0) { p4est_refine_ext (p4est, 1, maxlevel, p4est_points_refine, p4est_points_init, NULL); #ifdef P4EST_ENABLE_DEBUG for (jt = first_tree; jt <= last_tree; ++jt) { tree = p4est_tree_array_index (p4est->trees, jt); first_quad = p4est_quadrant_array_index (&tree->quadrants, 0); for (zz = 1; zz < tree->quadrants.elem_count; ++zz) { next_quad = p4est_quadrant_array_index (&tree->quadrants, zz); P4EST_ASSERT (((p4est_locidx_t *) first_quad->p.user_data)[1] == ((p4est_locidx_t *) next_quad->p.user_data)[0]); first_quad = next_quad; } } #endif } /* initialize user pointer and data size */ p4est_reset_data (p4est, data_size, init_fn, user_pointer); return p4est; }
static p4est_wrap_leaf_t * p4est_wrap_leaf_info (p4est_wrap_leaf_t * leaf) { #ifdef P4EST_ENABLE_DEBUG p4est_t *p4est = leaf->pp->p4est; #endif #if 0 p4est_quadrant_t corner; #endif p4est_quadrant_t *mirror; /* complete information on current quadrant */ leaf->local_quad = leaf->tree->quadrants_offset + leaf->which_quad; leaf->quad = p4est_quadrant_array_index (leaf->tquadrants, leaf->which_quad); #if 0 p4est_qcoord_to_vertex (leaf->pp->conn, leaf->which_tree, leaf->quad->x, leaf->quad->y, #ifdef P4_TO_P8 leaf->quad->z, #endif leaf->lowerleft); p4est_quadrant_corner_node (leaf->quad, P4EST_CHILDREN - 1, &corner); p4est_qcoord_to_vertex (leaf->pp->conn, leaf->which_tree, corner.x, corner.y, #ifdef P4_TO_P8 corner.z, #endif leaf->upperright); #endif #if 0 #ifdef P4EST_ENABLE_DEBUG printf ("C: Leaf level %d tree %d tree_leaf %d local_leaf %d\n", (int) leaf->quad->level, leaf->which_tree, leaf->which_quad, leaf->local_quad); #endif #endif /* track parallel mirror quadrants */ if (leaf->mirrors != NULL) { if (leaf->local_quad == leaf->next_mirror_quadrant) { if (++leaf->nm + 1 < (p4est_locidx_t) leaf->mirrors->elem_count) { mirror = p4est_quadrant_array_index (leaf->mirrors, leaf->nm + 1); leaf->next_mirror_quadrant = mirror->p.piggy3.local_num; P4EST_ASSERT (leaf->next_mirror_quadrant > leaf->local_quad); P4EST_ASSERT (leaf->next_mirror_quadrant < p4est->local_num_quadrants); } else { leaf->next_mirror_quadrant = -1; } leaf->is_mirror = 1; } else { leaf->is_mirror = 0; } } return leaf; }
int main (int argc, char **argv) { sc_MPI_Comm mpicomm; int mpiret; int mpisize, mpirank; unsigned crc; #ifndef P4_TO_P8 size_t kz; int8_t l; p4est_quadrant_t *q; p4est_tree_t stree, *tree = &stree; #endif p4est_t *p4est; p4est_connectivity_t *connectivity; /* initialize MPI */ mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); mpicomm = sc_MPI_COMM_WORLD; mpiret = sc_MPI_Comm_size (mpicomm, &mpisize); SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_rank (mpicomm, &mpirank); SC_CHECK_MPI (mpiret); sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT); p4est_init (NULL, SC_LP_DEFAULT); #ifndef P4_TO_P8 connectivity = p4est_connectivity_new_star (); #else connectivity = p8est_connectivity_new_rotcubes (); #endif p4est = p4est_new_ext (mpicomm, connectivity, 0, 0, 0, 4, NULL, NULL); #ifndef P4_TO_P8 /* build empty tree */ sc_array_init (&tree->quadrants, sizeof (p4est_quadrant_t)); for (l = 0; l <= P4EST_MAXLEVEL; ++l) { tree->quadrants_per_level[l] = 0; } tree->maxlevel = 0; /* insert two quadrants */ sc_array_resize (&tree->quadrants, 4); q = p4est_quadrant_array_index (&tree->quadrants, 0); p4est_quadrant_set_morton (q, 3, 13); q = p4est_quadrant_array_index (&tree->quadrants, 1); p4est_quadrant_set_morton (q, 1, 1); q = p4est_quadrant_array_index (&tree->quadrants, 2); p4est_quadrant_set_morton (q, 1, 2); q = p4est_quadrant_array_index (&tree->quadrants, 3); p4est_quadrant_set_morton (q, 1, 3); for (kz = 0; kz < tree->quadrants.elem_count; ++kz) { q = p4est_quadrant_array_index (&tree->quadrants, kz); q->p.user_data = sc_mempool_alloc (p4est->user_data_pool); ++tree->quadrants_per_level[q->level]; tree->maxlevel = (int8_t) SC_MAX (tree->maxlevel, q->level); } /* balance the tree, print and destroy */ #if 0 p4est_balance_subtree (p4est, P4EST_CONNECT_FULL, 0, NULL); p4est_tree_print (SC_LP_INFO, tree); #endif for (kz = 0; kz < tree->quadrants.elem_count; ++kz) { q = p4est_quadrant_array_index (&tree->quadrants, kz); sc_mempool_free (p4est->user_data_pool, q->p.user_data); } sc_array_reset (&tree->quadrants); #endif /* !P4_TO_P8 */ /* check reset data function */ p4est_reset_data (p4est, 0, init_fn, NULL); p4est_reset_data (p4est, 0, NULL, NULL); /* refine and balance the forest */ SC_CHECK_ABORT (p4est_is_balanced (p4est, P4EST_CONNECT_FULL), "Balance 1"); p4est_refine (p4est, 1, refine_fn, NULL); SC_CHECK_ABORT (!p4est_is_balanced (p4est, P4EST_CONNECT_FULL), "Balance 2"); p4est_balance (p4est, P4EST_CONNECT_FULL, NULL); SC_CHECK_ABORT (p4est_is_balanced (p4est, P4EST_CONNECT_FULL), "Balance 3"); /* check reset data function */ p4est_reset_data (p4est, 17, NULL, NULL); p4est_reset_data (p4est, 8, init_fn, NULL); /* checksum and partition */ crc = p4est_checksum (p4est); p4est_partition (p4est, 0, NULL); SC_CHECK_ABORT (p4est_checksum (p4est) == crc, "Partition"); SC_CHECK_ABORT (p4est_is_balanced (p4est, P4EST_CONNECT_FULL), "Balance 4"); /* check reset data function */ p4est_reset_data (p4est, 3, NULL, NULL); p4est_reset_data (p4est, 3, NULL, NULL); /* checksum and rebalance */ crc = p4est_checksum (p4est); p4est_balance (p4est, P4EST_CONNECT_FULL, NULL); SC_CHECK_ABORT (p4est_checksum (p4est) == crc, "Rebalance"); /* clean up and exit */ P4EST_ASSERT (p4est->user_data_pool->elem_count == (size_t) p4est->local_num_quadrants); p4est_destroy (p4est); p4est_connectivity_destroy (connectivity); sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
int main (int argc, char *argv[]) { MPI_Comm comm = MPI_COMM_WORLD; p4est_t *p4est; p4est_connectivity_t *conn; p4est_ghost_t *ghost_layer; p4est_lnodes_t *lnodes; int rank; const int degree = 1; BFAM_MPI_CHECK(MPI_Init(&argc,&argv)); BFAM_MPI_CHECK(MPI_Comm_rank(comm, &rank)); bfam_log_init(rank, stdout, BFAM_LL_DEFAULT); bfam_signal_handler_set(); sc_init(comm, 0, 0, NULL, SC_LP_DEFAULT); p4est_init(NULL, SC_LP_DEFAULT); conn = p4est_connectivity_new_corner(); p4est = p4est_new_ext(comm, conn, 0, 0, 0, 0, NULL, NULL); refine_level = 1; p4est_refine(p4est, 1, refine_fn, NULL); p4est_balance(p4est, P4EST_CONNECT_FACE, NULL); p4est_partition(p4est, 1, NULL); p4est_vtk_write_file(p4est, NULL, "mesh"); ghost_layer = p4est_ghost_new(p4est, P4EST_CONNECT_FULL); lnodes = p4est_lnodes_new(p4est, ghost_layer, degree); /* * Output the mesh. It can be read using something like following command: * * mpirun -np 3 ./bfam_exam_p4est | grep MESH | sort -n -k 2 | sort -n -k 5 | gvim - */ fflush(stdout); BFAM_MPI_CHECK(MPI_Barrier(comm)); BFAM_ROOT_INFO("MESH 0 ------------ Mesh Begin ------------"); BFAM_ROOT_INFO("MESH 1 degree = %d", lnodes->degree); BFAM_ROOT_INFO("MESH 2 vnodes = %d", lnodes->vnodes); BFAM_INFO("MESH 3 num_local_elements = %jd", (intmax_t)lnodes->num_local_elements); BFAM_INFO("MESH 4 num_local_nodes = %jd", (intmax_t)lnodes->num_local_nodes); BFAM_INFO("MESH 5 owned_count = %jd", (intmax_t)lnodes->owned_count); BFAM_INFO("MESH 6 global_offset = %jd", (intmax_t)lnodes->global_offset); sc_array_t *global_nodes = sc_array_new(sizeof (p4est_gloidx_t)); sc_array_resize(global_nodes, lnodes->num_local_nodes); for(size_t zz = 0; zz < global_nodes->elem_count; ++zz) { *((p4est_gloidx_t *) sc_array_index(global_nodes, zz)) = p4est_lnodes_global_index(lnodes, zz); } p4est_lnodes_share_owned(global_nodes, lnodes); for(size_t zz = 0; zz < global_nodes->elem_count; ++zz) { const p4est_gloidx_t gn = *((p4est_gloidx_t *)sc_array_index(global_nodes, zz)); SC_CHECK_ABORT (gn == p4est_lnodes_global_index(lnodes, zz), "Lnodes: bad global index across procesors"); BFAM_INFO("MESH 7 global_nodes[%zu] = %jd", zz, (intmax_t)gn); } sc_array_destroy(global_nodes); p4est_topidx_t flt = p4est->first_local_tree; p4est_topidx_t llt = p4est->last_local_tree; p4est_locidx_t elid, elnid; p4est_topidx_t t; const double *v = conn->vertices; const p4est_topidx_t *tree_to_vertex = conn->tree_to_vertex; for(elid = 0, elnid = 0, t = flt; t <= llt; ++t) { p4est_tree_t *tree = p4est_tree_array_index(p4est->trees, t); const size_t count = tree->quadrants.elem_count; p4est_topidx_t vt[P4EST_CHILDREN]; for (int c = 0; c < P4EST_CHILDREN; ++c) { vt[c] = tree_to_vertex[t * P4EST_CHILDREN + c]; } for (size_t zz = 0; zz < count; ++zz, ++elid) { p4est_quadrant_t *q = p4est_quadrant_array_index(&tree->quadrants, zz); for(int jind = 0; jind < degree + 1; ++jind) { for(int iind = 0; iind < degree + 1; ++iind, ++elnid) { double xyz[3]; for (int j = 0; j < 3; ++j) { const p4est_qcoord_t len = P4EST_QUADRANT_LEN(q->level); const double rlen = (double) P4EST_ROOT_LEN; const double deg = (double) degree; const double qlen = ((double) len) / rlen; const double eta_x = ((double) q->x) / rlen + (((double) iind) / deg) * qlen; const double eta_y = ((double) q->y) / rlen + (((double) jind) / deg) * qlen; xyz[j] = ((1. - eta_y) * ((1. - eta_x) * v[3 * vt[0] + j] + eta_x * v[3 * vt[1] + j]) + eta_y * ((1. - eta_x) * v[3 * vt[2] + j] + eta_x * v[3 * vt[3] + j])); } const p4est_locidx_t nid = lnodes->element_nodes[elnid]; BFAM_INFO( "MESH 8 local_node[%03jd] = %03jd ( %25.16e %25.16e %25.16e )", (intmax_t)elnid, (intmax_t)nid, xyz[0], xyz[1], xyz[2]); } } } } BFAM_ROOT_INFO("MESH 9 ------------ Mesh End ------------"); p4est_lnodes_destroy(lnodes); p4est_ghost_destroy(ghost_layer); p4est_destroy(p4est); p4est_connectivity_destroy(conn); sc_finalize(); BFAM_MPI_CHECK(MPI_Finalize()); return EXIT_SUCCESS; }