static void coords_double_to_PetscScalar (sc_array_t * array) { sc_array_t *newarray; size_t zz, count = array->elem_count; P4EST_ASSERT (array->elem_size == 3 * sizeof (double)); if (sizeof (double) == sizeof (PetscScalar)) { return; } newarray = sc_array_new_size (3 * sizeof (PetscScalar), array->elem_count); for (zz = 0; zz < count; zz++) { double *id = (double *) sc_array_index (array, zz); PetscScalar *ip = (PetscScalar *) sc_array_index (newarray, zz); ip[0] = (PetscScalar) id[0]; ip[1] = (PetscScalar) id[1]; ip[2] = (PetscScalar) id[2]; } sc_array_reset (array); sc_array_init_size (array, 3 * sizeof (PetscScalar), count); sc_array_copy (array, newarray); sc_array_destroy (newarray); }
static void p6est_profile_compress (p6est_profile_t * profile) { p4est_locidx_t nidx, il, old_off, nln = profile->lnodes->num_local_nodes; p4est_locidx_t (*lr)[2] = (p4est_locidx_t (*)[2]) profile->lnode_ranges; sc_array_t *lc = profile->lnode_columns; size_t old_count = lc->elem_count; size_t new_count; sc_array_t *perm; size_t *newindex; size_t zz, offset; if (!old_count) { return; } perm = sc_array_new_size (sizeof (size_t), old_count); newindex = (size_t *) sc_array_index (perm, 0); for (zz = 0; zz < old_count; zz++) { newindex[zz] = old_count; } offset = 0; for (nidx = 0; nidx < nln; nidx++) { old_off = lr[nidx][0]; if (lr[nidx][1]) { lr[nidx][0] = offset; } else { P4EST_ASSERT (!lr[nidx][0]); } for (il = 0; il < lr[nidx][1]; il++) { newindex[il + old_off] = offset++; } } new_count = offset; for (zz = 0; zz < old_count; zz++) { if (newindex[zz] == old_count) { newindex[zz] = offset++; } } sc_array_permute (lc, perm, 0); sc_array_destroy (perm); sc_array_resize (lc, new_count); }
static void locidx_pair_to_PetscSFNode (sc_array_t * array) { sc_array_t *newarray; size_t zz, count = array->elem_count; P4EST_ASSERT (array->elem_size == 2 * sizeof (p4est_locidx_t)); newarray = sc_array_new_size (sizeof (PetscSFNode), array->elem_count); for (zz = 0; zz < count; zz++) { p4est_locidx_t *il = (p4est_locidx_t *) sc_array_index (array, zz); PetscSFNode *ip = (PetscSFNode *) sc_array_index (newarray, zz); ip->rank = (PetscInt) il[0]; ip->index = (PetscInt) il[1]; } sc_array_reset (array); sc_array_init_size (array, sizeof (PetscSFNode), count); sc_array_copy (array, newarray); sc_array_destroy (newarray); }
static void locidx_to_PetscInt (sc_array_t * array) { sc_array_t *newarray; size_t zz, count = array->elem_count; P4EST_ASSERT (array->elem_size == sizeof (p4est_locidx_t)); if (sizeof (p4est_locidx_t) == sizeof (PetscInt)) { return; } newarray = sc_array_new_size (sizeof (PetscInt), array->elem_count); for (zz = 0; zz < count; zz++) { p4est_locidx_t il = *((p4est_locidx_t *) sc_array_index (array, zz)); PetscInt *ip = (PetscInt *) sc_array_index (newarray, zz); *ip = (PetscInt) il; } sc_array_reset (array); sc_array_init_size (array, sizeof (PetscInt), count); sc_array_copy (array, newarray); sc_array_destroy (newarray); }
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; }
static void test_build_local (sc_MPI_Comm mpicomm) { sc_array_t *points; p4est_connectivity_t *conn; p4est_t *p4est, *built, *copy; test_build_t stb, *tb = &stb; /* 0. prepare data that we will reuse */ tb->maxlevel = 7 - P4EST_DIM; tb->counter = -1; tb->wrapper = 3; tb->init_default = -1; tb->init_add = -1; tb->count_add = -1; tb->last_tree = -1; tb->build = NULL; #ifndef P4_TO_P8 conn = p4est_connectivity_new_moebius (); #else conn = p8est_connectivity_new_rotcubes (); #endif /* P4_TO_P8 */ p4est = p4est_new_ext (mpicomm, conn, 0, 0, 2, 0, NULL, tb); p4est_refine (p4est, 1, test_build_refine, NULL); p4est_partition (p4est, 0, NULL); /* TODO: enrich tests with quadrant data */ /* 1. Create a p4est that shall be identical to the old one. */ tb->build = p4est_build_new (p4est, 0, NULL, NULL); p4est_search_local (p4est, 0, test_search_local_1, NULL, NULL); built = p4est_build_complete (tb->build); SC_CHECK_ABORT (p4est_is_equal (p4est, built, 0), "Mismatch build_local 1"); p4est_destroy (built); /* 2. Create a p4est that is as coarse as possible. * Coarsen recursively, compare. */ tb->build = p4est_build_new (p4est, 4, NULL, NULL); p4est_search_local (p4est, 0, test_search_local_2, NULL, NULL); built = p4est_build_complete (tb->build); copy = p4est_copy (p4est, 0); p4est_coarsen (copy, 1, test_build_coarsen, NULL); SC_CHECK_ABORT (p4est_is_equal (copy, built, 0), "Mismatch build_local 2"); p4est_destroy (copy); p4est_destroy (built); /* 3. Create a p4est with some random pattern for demonstration */ tb->init_default = 0; tb->init_add = 0; tb->count_add = 0; tb->build = p4est_build_new (p4est, 0, test_search_init_3, tb); p4est_build_init_add (tb->build, test_search_init_add_3); p4est_search_local (p4est, 1, test_search_local_3, NULL, NULL); built = p4est_build_complete (tb->build); p4est_build_verify_3 (built); SC_CHECK_ABORT (p4est_is_valid (built), "Invalid build_local 3"); p4est_destroy (built); /* 4. Create a p4est from a search with one quadrant per tree */ tb->init_default = 0; tb->init_add = 0; tb->count_add = 0; tb->last_tree = -1; tb->build = p4est_build_new (p4est, sizeof (long), test_search_init_4, tb); p4est_build_init_add (tb->build, test_search_init_add_4); p4est_search_local (p4est, 0, test_search_local_4, NULL, NULL); built = p4est_build_complete (tb->build); p4est_build_verify_4 (built); SC_CHECK_ABORT (p4est_is_valid (built), "Invalid build_local 4"); p4est_destroy (built); /* 5. Create a p4est from a multiple-item search */ points = sc_array_new_size (sizeof (int8_t), 2); *(int8_t *) sc_array_index (points, 0) = 0; *(int8_t *) sc_array_index (points, 1) = 1; tb->wrapper = 5; tb->init_default = 0; tb->init_add = 0; tb->build = p4est_build_new (p4est, 0, NULL, tb); p4est_search_local (p4est, 0, NULL, test_search_point_5, points); built = p4est_build_complete (tb->build); #if 0 p4est_build_verify_5 (built); #endif SC_CHECK_ABORT (p4est_is_valid (built), "Invalid build_local 5"); p4est_destroy (built); sc_array_destroy (points); /* clean up */ p4est_destroy (p4est); p4est_connectivity_destroy (conn); }
p6est_lnodes_t * p6est_lnodes_new (p6est_t * p6est, p6est_ghost_t * ghost, int degree) { p6est_lnodes_t *lnodes; p6est_profile_t *profile; p4est_lnodes_t *clnodes; int nperelem = (degree + 1) * (degree + 1) * (degree + 1); /* int nperface = (degree - 1) * (degree - 1); */ /* int nperedge = (degree - 1); */ p4est_locidx_t ncid, cid, enid, *en; p4est_locidx_t nnodecols; p4est_locidx_t nelemcols; p4est_locidx_t nll; p4est_locidx_t nlayers; p4est_locidx_t *layernodecount; p4est_locidx_t *layernodeoffsets; p4est_locidx_t (*lr)[2]; p4est_locidx_t ncolnodes; p4est_locidx_t *global_owned_count; p4est_locidx_t num_owned, num_local; p4est_gloidx_t gnum_owned, offset; p4est_gloidx_t *owned_offsets; int i, j, k; int mpisize = p6est->mpisize; int mpiret; sc_array_t lnoview; size_t zz, nsharers; int Nrp = degree + 1; if (degree == 1) { p4est_locidx_t eid, nid, enid2, nid2; p4est_locidx_t *newnum, newlocal, newowned; P4EST_GLOBAL_PRODUCTION ("Into adapt p6est_lnodes_new for degree = 1\n"); p4est_log_indent_push (); /* adapt 2 to 1 */ lnodes = p6est_lnodes_new (p6est, ghost, 2); nll = p6est->layers->elem_count; num_local = lnodes->num_local_nodes; num_owned = lnodes->owned_count; en = lnodes->element_nodes; newnum = P4EST_ALLOC (p4est_locidx_t, P8EST_INSUL * nll); memset (newnum, -1, P8EST_INSUL * nll * sizeof (p4est_locidx_t)); for (enid = 0, eid = 0; eid < nll; eid++) { for (k = 0; k < 3; k++) { for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++, enid++) { if (k != 1 && j != 1 && i != 1) { newnum[en[enid]] = 0; } } } } } newlocal = 0; newowned = 0; for (nid = 0; nid < num_local; nid++) { if (newnum[nid] >= 0) { newnum[nid] = newlocal++; if (nid < num_owned) { newowned++; } } } /* compress en */ enid2 = 0; for (enid = 0, eid = 0; eid < nll; eid++) { for (k = 0; k < 3; k++) { for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++, enid++) { if (k != 1 && j != 1 && i != 1) { en[enid2++] = newnum[en[enid]]; } } } } } P4EST_ASSERT (enid2 == P8EST_CHILDREN * nll); lnodes->element_nodes = P4EST_REALLOC (en, p4est_locidx_t, P8EST_CHILDREN * nll); owned_offsets = P4EST_ALLOC (p4est_gloidx_t, mpisize + 1); mpiret = sc_MPI_Allgather (&newowned, 1, P4EST_MPI_LOCIDX, lnodes->global_owned_count, 1, P4EST_MPI_LOCIDX, p6est->mpicomm); owned_offsets[0] = 0; for (i = 0; i < mpisize; i++) { owned_offsets[i + 1] = owned_offsets[i] + lnodes->global_owned_count[i]; } lnodes->global_offset = owned_offsets[p6est->mpirank]; lnodes->num_local_nodes = newlocal; lnodes->owned_count = newowned; lnodes->degree = 1; lnodes->vnodes = P8EST_CHILDREN; lnodes->nonlocal_nodes = P4EST_REALLOC (lnodes->nonlocal_nodes, p4est_gloidx_t, newlocal - newowned); nsharers = lnodes->sharers->elem_count; for (zz = 0; zz < nsharers; zz++) { size_t nshared, zy, zw; p6est_lnodes_rank_t *rank = p6est_lnodes_rank_array_index (lnodes->sharers, zz); if (rank->owned_count) { if (rank->rank != p6est->mpirank) { p4est_locidx_t newrankowned = 0; p4est_locidx_t newrankoffset = -1; for (nid = rank->owned_offset; nid < rank->owned_offset + rank->owned_count; nid++) { if (newnum[nid] >= 0) { lnodes->nonlocal_nodes[newnum[nid] - newowned] = owned_offsets[rank->rank]; newrankowned++; if (newrankoffset < 0) { newrankoffset = newnum[nid]; } } } rank->owned_offset = newrankoffset; rank->owned_count = newrankowned; } else { rank->owned_offset = 0; rank->owned_count = newowned; } } rank->shared_mine_count = 0; rank->shared_mine_offset = -1; zw = 0; nshared = rank->shared_nodes.elem_count; for (zy = 0; zy < nshared; zy++) { nid = *((p4est_locidx_t *) sc_array_index (&rank->shared_nodes, zy)); if (newnum[nid] >= 0) { p4est_locidx_t *lp; lp = (p4est_locidx_t *) sc_array_index (&rank->shared_nodes, zw++); *lp = newnum[nid]; if (newnum[nid] < newowned) { rank->shared_mine_count++; if (rank->shared_mine_offset == -1) { rank->shared_mine_offset = zw - 1; } } } } sc_array_resize (&rank->shared_nodes, zw); } /* send local numbers to others */ { sc_array_t view; sc_array_init_data (&view, newnum, sizeof (p4est_locidx_t), newlocal); p6est_lnodes_share_owned (&view, lnodes); } nid2 = 0; for (nid = num_owned; nid < num_local; nid++) { if (newnum[nid] >= 0) { lnodes->nonlocal_nodes[nid2++] += (p4est_gloidx_t) newnum[nid]; } } P4EST_ASSERT (nid2 == newlocal - newowned); P4EST_FREE (owned_offsets); P4EST_FREE (newnum); p4est_log_indent_pop (); P4EST_GLOBAL_PRODUCTION ("Done adapt p6est_lnodes_new for degree = 1\n"); return lnodes; } P4EST_GLOBAL_PRODUCTION ("Into p6est_lnodes_new\n"); p4est_log_indent_push (); P4EST_ASSERT (degree >= 1); lnodes = P4EST_ALLOC (p6est_lnodes_t, 1); /* first get the profile */ profile = p6est_profile_new_local (p6est, ghost, P6EST_PROFILE_INTERSECTION, P8EST_CONNECT_FULL, degree); p6est_profile_sync (profile); lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges; clnodes = profile->lnodes; nnodecols = clnodes->num_local_nodes; nelemcols = clnodes->num_local_elements; en = clnodes->element_nodes; layernodecount = P4EST_ALLOC_ZERO (p4est_locidx_t, nnodecols); layernodeoffsets = P4EST_ALLOC_ZERO (p4est_locidx_t, nnodecols + 1); for (cid = 0, enid = 0; cid < nelemcols; cid++) { for (j = 0; j < Nrp; j++) { for (i = 0; i < Nrp; i++, enid++) { ncid = en[enid]; nlayers = lr[ncid][1]; P4EST_ASSERT (nlayers); ncolnodes = nlayers * degree + 1; layernodecount[ncid] = ncolnodes; } } } num_owned = 0; num_local = 0; for (ncid = 0; ncid < nnodecols; ncid++) { num_local += layernodecount[ncid]; if (ncid < clnodes->owned_count) { num_owned += layernodecount[ncid]; } } P4EST_VERBOSEF ("p6est_lnodes: %d owned %d local\n", num_owned, num_local); if (nnodecols) { layernodeoffsets[0] = 0; for (ncid = 0; ncid < nnodecols; ncid++) { layernodeoffsets[ncid + 1] = layernodeoffsets[ncid] + layernodecount[ncid]; } } gnum_owned = num_owned; owned_offsets = P4EST_ALLOC (p4est_gloidx_t, mpisize + 1); global_owned_count = P4EST_ALLOC (p4est_locidx_t, mpisize); mpiret = sc_MPI_Allgather (&gnum_owned, 1, P4EST_MPI_GLOIDX, owned_offsets, 1, P4EST_MPI_GLOIDX, p6est->mpicomm); SC_CHECK_MPI (mpiret); offset = 0; for (i = 0; i < mpisize; i++) { global_owned_count[i] = (p4est_locidx_t) owned_offsets[i]; gnum_owned = owned_offsets[i]; owned_offsets[i] = offset; offset += gnum_owned; } owned_offsets[mpisize] = offset; nll = p6est->layers->elem_count; nsharers = clnodes->sharers->elem_count; lnodes->mpicomm = p6est->mpicomm; lnodes->num_local_nodes = num_local; lnodes->owned_count = num_owned; lnodes->global_offset = owned_offsets[p6est->mpirank]; lnodes->nonlocal_nodes = P4EST_ALLOC (p4est_gloidx_t, num_local - num_owned); lnodes->sharers = sc_array_new_size (sizeof (p6est_lnodes_rank_t), nsharers); lnodes->global_owned_count = global_owned_count; lnodes->degree = degree; lnodes->vnodes = nperelem; lnodes->num_local_elements = nll; lnodes->face_code = P4EST_ALLOC (p6est_lnodes_code_t, nll); lnodes->element_nodes = P4EST_ALLOC (p4est_locidx_t, nperelem * nll); p6est_profile_element_to_node (p6est, profile, layernodeoffsets, lnodes->element_nodes, lnodes->face_code); for (zz = 0; zz < nsharers; zz++) { p4est_lnodes_rank_t *crank = p4est_lnodes_rank_array_index (clnodes->sharers, zz); p6est_lnodes_rank_t *rank = p6est_lnodes_rank_array_index (lnodes->sharers, zz); size_t zy; size_t nshared; rank->rank = crank->rank; sc_array_init (&rank->shared_nodes, sizeof (p4est_locidx_t)); nshared = crank->shared_nodes.elem_count; rank->owned_offset = -1; rank->owned_count = 0; rank->shared_mine_count = 0; rank->shared_mine_offset = -1; for (zy = 0; zy < nshared; zy++) { p4est_locidx_t cnid = *((p4est_locidx_t *) sc_array_index (&crank->shared_nodes, zy)); p4est_locidx_t *lp; p4est_locidx_t nthis, il; p4est_locidx_t old_count = rank->shared_nodes.elem_count; nthis = layernodecount[cnid]; lp = (p4est_locidx_t *) sc_array_push_count (&rank->shared_nodes, nthis); for (il = 0; il < nthis; il++) { lp[il] = layernodeoffsets[cnid] + il; if (zy >= (size_t) crank->shared_mine_offset && (p4est_locidx_t) zy - crank->shared_mine_offset < crank->shared_mine_count) { rank->shared_mine_count++; if (rank->shared_mine_offset == -1) { rank->shared_mine_offset = old_count + il; } } if (cnid >= crank->owned_offset && cnid - crank->owned_offset < crank->owned_count) { rank->owned_count++; if (rank->owned_offset == -1) { rank->owned_offset = lp[il]; } } } } if (rank->rank == p6est->mpirank) { rank->owned_offset = 0; rank->owned_count = num_owned; } } memcpy (layernodecount, layernodeoffsets, nnodecols * sizeof (p4est_locidx_t)); sc_array_init_data (&lnoview, layernodecount, sizeof (p4est_locidx_t), (size_t) nnodecols); p4est_lnodes_share_owned (&lnoview, clnodes); for (zz = 0; zz < nsharers; zz++) { p4est_lnodes_rank_t *crank = p4est_lnodes_rank_array_index (clnodes->sharers, zz); if (crank->rank == p6est->mpirank) { continue; } for (ncid = crank->owned_offset; ncid < crank->owned_offset + crank->owned_count; ncid++) { p4est_gloidx_t owners_offset; p4est_locidx_t nid; P4EST_ASSERT (ncid >= clnodes->owned_count); owners_offset = owned_offsets[crank->rank] + layernodecount[ncid]; for (nid = layernodeoffsets[ncid]; nid < layernodeoffsets[ncid + 1]; nid++) { P4EST_ASSERT (nid >= num_owned); P4EST_ASSERT (nid < num_local); lnodes->nonlocal_nodes[nid - num_owned] = owners_offset++; } } } p6est_profile_destroy (profile); P4EST_FREE (owned_offsets); P4EST_FREE (layernodecount); P4EST_FREE (layernodeoffsets); p4est_log_indent_pop (); P4EST_GLOBAL_PRODUCTION ("Done p6est_lnodes_new\n"); return lnodes; }