/* This is the kernel for 3d balance with face balancing only */ static inline int p8est_balance_kernel_3d_face (p4est_qcoord_t dx, p4est_qcoord_t dy, p4est_qcoord_t dz, int level) { int shift = P4EST_MAXLEVEL - level; int maxbit; int yzbit, zxbit, xybit; p4est_qcoord_t dyz, dzx, dxy, bitwor; int ret; P4EST_ASSERT (dx >= 0); P4EST_ASSERT (!(dx & (~(((p4est_qcoord_t) - 1) << shift)))); P4EST_ASSERT (dy >= 0); P4EST_ASSERT (!(dy & (~(((p4est_qcoord_t) - 1) << shift)))); P4EST_ASSERT (dz >= 0); P4EST_ASSERT (!(dz & (~(((p4est_qcoord_t) - 1) << shift)))); if (!dx && !dy && !dz) { return level; } dx >>= shift; /* get the smallest even number greater than or equal to dx */ dx = (dx + 1) & (~((p4est_qcoord_t) 0x1)); dy >>= shift; /* get the smallest even number greater than or equal to dy */ dy = (dy + 1) & (~((p4est_qcoord_t) 0x1)); dz >>= shift; /* get the smallest even number greater than or equal to dz */ dz = (dz + 1) & (~((p4est_qcoord_t) 0x1)); /* this problem is dual to dual to kernel 3d edge */ dyz = dy + dz; dzx = dz + dx; dxy = dx + dy; yzbit = SC_LOG2_32 (dyz); maxbit = yzbit; zxbit = SC_LOG2_32 (dzx); maxbit = SC_MAX (maxbit, zxbit); xybit = SC_LOG2_32 (dxy); maxbit = SC_MAX (maxbit, xybit); P4EST_ASSERT (maxbit >= 1); /* we want to carry a 1 when there are three 1 bits, so we find places * where there is at least one 1 bit and subtract one 1 bit: then if we * sum, the binary carry rule will give the correct result */ bitwor = (dyz | dzx | dxy); ret = SC_LOG2_32 (dyz + dzx + dxy - bitwor); /* we have to guard against the case when the leading position has one 1 * bit. */ ret = SC_MAX (maxbit, ret); return SC_MAX (0, level - ret); }
static void p6est_profile_balance_full_one_pass (sc_array_t * read, sc_array_t * write, p4est_qcoord_t readh) { int8_t *wc; size_t count; int stackcount; int8_t n, nn, newn, p, l, prevl, nextl; size_t zy; P4EST_ASSERT (SC_ARRAY_IS_OWNER (write)); P4EST_ASSERT (read->elem_size == sizeof (int8_t)); P4EST_ASSERT (write->elem_size == sizeof (int8_t)); count = read->elem_count; sc_array_truncate (write); l = 0; zy = 0; while (zy < count) { n = *((int8_t *) sc_array_index (read, count - 1 - zy++)); if (n && !(readh & P4EST_QUADRANT_LEN (n))) { P4EST_ASSERT (zy < count); nn = *((int8_t *) sc_array_index (read, count - 1 - zy)); if (n == nn) { if (zy > 1) { prevl = *((int8_t *) sc_array_index (read, count - 1 - (zy - 2))); } else { prevl = -1; } if (zy < count - 1) { nextl = *((int8_t *) sc_array_index (read, count - 1 - (zy + 1))); } else { nextl = -1; } if (n >= SC_MAX (nextl, prevl) - 1) { zy++; n--; } } } readh += P4EST_QUADRANT_LEN (n); p = l - 1; newn = SC_MAX (p, n); stackcount = newn - n; wc = (int8_t *) sc_array_push_count (write, 1 + stackcount); *wc = l = newn; while (stackcount--) { *(++wc) = l = newn--; } } }
void sc_log_indent_pop_count (int package, int count) { /* TODO: figure out a version that makes sense with threads */ #ifndef SC_ENABLE_PTHREAD int new_indent; SC_ASSERT (package < sc_num_packages); if (package >= 0) { new_indent = sc_packages[package].log_indent - SC_MAX (0, count); sc_packages[package].log_indent = SC_MAX (0, new_indent); } #endif }
static void p6est_profile_balance_self_one_pass (sc_array_t * read, sc_array_t * write) { int stackcount; int8_t n, newn, p, l; int8_t *wc; size_t count = read->elem_count; size_t zy; P4EST_ASSERT (SC_ARRAY_IS_OWNER (write)); P4EST_ASSERT (read->elem_size == sizeof (int8_t)); P4EST_ASSERT (write->elem_size == sizeof (int8_t)); sc_array_truncate (write); wc = (int8_t *) sc_array_push (write); n = *((int8_t *) sc_array_index (read, count - 1)); *wc = l = n; for (zy = 1; zy < count; zy++) { n = *((int8_t *) sc_array_index (read, count - 1 - zy)); p = l - 1; newn = SC_MAX (p, n); stackcount = newn - n; wc = (int8_t *) sc_array_push_count (write, 1 + stackcount); *wc = l = newn; while (stackcount--) { *(++wc) = l = newn--; } } }
/* This is the kernel for 2D balance with face-only balancing */ static inline int p4est_balance_kernel_2d (p4est_qcoord_t dx, p4est_qcoord_t dy, int level) { int shift = P4EST_MAXLEVEL - level; p4est_qcoord_t distance; P4EST_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); /* the distance only makes sense if it is an integer number of \a level * distances */ P4EST_ASSERT (dx >= 0); P4EST_ASSERT (!(dx & (~(((p4est_qcoord_t) - 1) << shift)))); P4EST_ASSERT (dy >= 0); P4EST_ASSERT (!(dy & (~(((p4est_qcoord_t) - 1) << shift)))); dx >>= shift; /* get the smallest even number greater than or equal to dx */ dx = (dx + 1) & (~((p4est_qcoord_t) 0x1)); dy >>= shift; /* get the smallest even number greater than or equal to dy */ dy = (dy + 1) & (~((p4est_qcoord_t) 0x1)); /* the + 1 guarantees the correct answer even for (0, 0) */ distance = dx + dy + 1; return SC_MAX (0, level - SC_LOG2_32 (distance)); }
/** Compute the maximum state value. * * This function updates the maximum value from the value of a single cell. * * This function matches the p4est_iter_volume_t prototype used by * p4est_iterate(). * * \param [in] info the information about this quadrant that has been * populated by p4est_iterate() * \param [in,out] user_data the user_data given to p4est_iterate(): in this case, * it points to the maximum value that will be updated */ static void step3_compute_max (p4est_iter_volume_info_t * info, void *user_data) { p4est_quadrant_t *q = info->quad; step3_data_t *data = (step3_data_t *) q->p.user_data; double umax = *((double *) user_data); umax = SC_MAX (data->u, umax); *((double *) user_data) = umax; }
/* We have a location, and a \a level quadrant that must be shifted by * \a distance (>= 0) to be at the location. This returns the largest quadrant * that can exist at \a location and be in balance with the \a level quadrant. */ static inline int p4est_balance_kernel_1d (p4est_qcoord_t distance, int level) { int shift = P4EST_MAXLEVEL - level; P4EST_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); /* the distance only makes sense if it is an integer number of \a level * distances */ P4EST_ASSERT (distance >= 0); P4EST_ASSERT (!(distance & (~(((p4est_qcoord_t) - 1) << shift)))); distance >>= shift; /* The theory says we should use ((distance + 1)&(~1) + 1), but * using distance + 1 is equivalent for all distance >= 0 */ distance++; return SC_MAX (0, level - SC_LOG2_32 (distance)); }
/** Compute the timestep. * * Find the smallest quadrant and scale the timestep based on that length and * the advection velocity. * * \param [in] p4est the forest * \return the timestep. */ static double step3_get_timestep (p4est_t * p4est) { step3_ctx_t *ctx = (step3_ctx_t *) p4est->user_pointer; p4est_topidx_t t, flt, llt; p4est_tree_t *tree; int max_level, global_max_level; int mpiret, i; double min_h, vnorm; double dt; /* compute the timestep by finding the smallest quadrant */ flt = p4est->first_local_tree; llt = p4est->last_local_tree; max_level = 0; for (t = flt; t <= llt; t++) { tree = p4est_tree_array_index (p4est->trees, t); max_level = SC_MAX (max_level, tree->maxlevel); } mpiret = sc_MPI_Allreduce (&max_level, &global_max_level, 1, sc_MPI_INT, sc_MPI_MAX, p4est->mpicomm); SC_CHECK_MPI (mpiret); min_h = (double) P4EST_QUADRANT_LEN (global_max_level) / (double) P4EST_ROOT_LEN; vnorm = 0; for (i = 0; i < P4EST_DIM; i++) { vnorm += ctx->v[i] * ctx->v[i]; } vnorm = sqrt (vnorm); dt = min_h / 2. / vnorm; return dt; }
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) { 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; }
static void test_tree (p8est_geometry_t * geom, p4est_topidx_t which_tree, const double bounds[6], int N) { const double epsilon = 1e-8; int i, j, k, l, m; double h[3]; double xyz[4][3], XYZ[4][3]; double Jgeom[3][3], Jdisc[3][3]; double detD, detJ, fd, fg; double diffD, diffJ, maxJ; for (l = 0; l < 3; ++l) { h[l] = bounds[2 * l + 1] - bounds[2 * l]; } for (i = 0; i < N; ++i) { xyz[3][2] = ((N - (i + .5)) * bounds[4] + (i + .5) * bounds[5]) / N; for (j = 0; j < N; ++j) { xyz[3][1] = ((N - (j + .5)) * bounds[2] + (j + .5) * bounds[3]) / N; for (k = 0; k < N; ++k) { xyz[3][0] = ((N - (k + .5)) * bounds[0] + (k + .5) * bounds[1]) / N; /* compute transformed point */ geom->X (geom, which_tree, xyz[3], XYZ[3]); /* offset point three times in the coordinate directions */ for (l = 0; l < 3; ++l) { /* l runs in domain */ memcpy (xyz[l], xyz[3], 3 * sizeof (double)); xyz[l][l] += epsilon * h[l]; geom->X (geom, which_tree, xyz[l], XYZ[l]); for (m = 0; m < 3; ++m) { /* m runs in image domain */ Jdisc[m][l] = (XYZ[l][m] - XYZ[3][m]) / (epsilon * h[l]); } } detJ = geom->J (geom, which_tree, xyz[3], Jgeom); detD = geom->D (geom, which_tree, xyz[3]); /* compare results */ diffD = fabs (detD - detJ) / SC_MAX (detD, detJ); SC_CHECK_ABORTF (diffD < 1e-8, "Determinant mismatch %lld %g %g %g", (long long) which_tree, xyz[3][0], xyz[3][1], xyz[3][2]); diffJ = maxJ = 0.; for (l = 0; l < 3; ++l) { for (m = 0; m < 3; ++m) { fd = fabs (Jdisc[m][l]); fg = fabs (Jgeom[m][l]); maxJ = SC_MAX (maxJ, fd); maxJ = SC_MAX (maxJ, fg); diffJ += fabs (Jdisc[m][l] - Jgeom[m][l]); } } diffJ /= 3 * 3 * maxJ; SC_CHECK_ABORTF (diffJ < 100. * epsilon, "Jacobian mismatch %lld %g %g %g", (long long) which_tree, xyz[3][0], xyz[3][1], xyz[3][2]); } } } }
/** * Runs all tests. */ int main (int argc, char **argv) { const char *this_fn_name = P4EST_STRING "_test_subcomm"; /* options */ const p4est_locidx_t min_quadrants = 15; const int min_level = 4; const int fill_uniform = 0; /* parallel environment */ sc_MPI_Comm mpicomm = sc_MPI_COMM_WORLD; int mpisize, submpisize; int mpiret; #ifdef P4EST_ENABLE_DEBUG int rank; #endif /* p4est */ p4est_connectivity_t *connectivity; p4est_t *p4est; p4est_locidx_t *partition; /* initialize MPI */ mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); /* exit if MPI communicator cannot be reduced */ mpiret = sc_MPI_Comm_size (mpicomm, &mpisize); SC_CHECK_MPI (mpiret); if (mpisize == 1) { mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; } /* initialize p4est */ sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT); p4est_init (NULL, SC_LP_DEFAULT); /* create connectivity */ #ifdef P4_TO_P8 connectivity = p8est_connectivity_new_unitcube (); #else connectivity = p4est_connectivity_new_unitsquare (); #endif /* create p4est object */ p4est = p4est_new_ext (mpicomm, connectivity, min_quadrants, min_level, fill_uniform, 0, NULL, NULL); /* write vtk: new */ p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_subcomm_new"); /* set variables pertaining to the parallel environment */ #ifdef P4EST_ENABLE_DEBUG rank = p4est->mpirank; #endif submpisize = mpisize / 2; P4EST_ASSERT (submpisize <= p4est->global_num_quadrants); /* construct partitioning with empty ranks */ { p4est_locidx_t n_quads_per_proc, n_quads_leftover; int p; partition = P4EST_ALLOC (p4est_locidx_t, mpisize); n_quads_per_proc = p4est->global_num_quadrants / submpisize; n_quads_leftover = p4est->global_num_quadrants - (n_quads_per_proc * submpisize); for (p = 0; p < mpisize; p++) { if (p % 2) { /* if this rank will get quadrants */ partition[p] = n_quads_per_proc; } else { /* if this rank will be empty */ partition[p] = 0; } } partition[1] += n_quads_leftover; /* check partitioning */ #ifdef P4EST_ENABLE_DEBUG { p4est_gloidx_t sum = 0; for (p = 0; p < mpisize; p++) { sum += (p4est_gloidx_t) partition[p]; } P4EST_ASSERT (sum == p4est->global_num_quadrants); } #endif } /* * Test 1: Reduce MPI communicator to non-empty ranks */ P4EST_GLOBAL_INFOF ("%s: Into test 1\n", this_fn_name); { p4est_t *p4est_subcomm; int is_nonempty; /* create p4est copy and re-partition */ p4est_subcomm = p4est_copy_ext (p4est, 1, 1); (void) p4est_partition_given (p4est_subcomm, partition); /* write vtk: partitioned */ p4est_vtk_write_file (p4est_subcomm, NULL, P4EST_STRING "_subcomm_part"); /* reduce MPI communicator to non-empty ranks */ is_nonempty = p4est_comm_parallel_env_reduce (&p4est_subcomm); P4EST_ASSERT ((is_nonempty && 0 < partition[rank]) || (!is_nonempty && 0 == partition[rank])); if (is_nonempty) { /* write vtk: reduced communicator */ p4est_vtk_write_file (p4est_subcomm, NULL, P4EST_STRING "_subcomm_sub1"); /* destroy the p4est that has a reduced MPI communicator */ p4est_destroy (p4est_subcomm); } } mpiret = sc_MPI_Barrier (mpicomm); SC_CHECK_MPI (mpiret); P4EST_GLOBAL_INFOF ("%s: Done test 1\n", this_fn_name); /* * Test 2: Reduce MPI communicator to non-empty ranks, but now the MPI * communicator is not owned */ P4EST_GLOBAL_INFOF ("%s: Into test 2\n", this_fn_name); { p4est_t *p4est_subcomm; int is_nonempty; /* create p4est copy and re-partition */ p4est_subcomm = p4est_copy_ext (p4est, 1, 0 /* don't dup. comm. */ ); (void) p4est_partition_given (p4est_subcomm, partition); /* reduce MPI communicator to non-empty ranks */ is_nonempty = p4est_comm_parallel_env_reduce (&p4est_subcomm); P4EST_ASSERT ((is_nonempty && 0 < partition[rank]) || (!is_nonempty && 0 == partition[rank])); if (is_nonempty) { /* destroy the p4est that has a reduced MPI communicator */ p4est_destroy (p4est_subcomm); } } mpiret = sc_MPI_Barrier (mpicomm); SC_CHECK_MPI (mpiret); P4EST_GLOBAL_INFOF ("%s: Done test 2\n", this_fn_name); /* * Test 3: Reduce MPI communicator to non-empty ranks, but keep rank 0 */ P4EST_GLOBAL_INFOF ("%s: Into test 3\n", this_fn_name); { p4est_t *p4est_subcomm; int sub_exists; sc_MPI_Group group, group_reserve; int reserve_range[1][3]; /* create group of full MPI communicator */ mpiret = sc_MPI_Comm_group (mpicomm, &group); SC_CHECK_MPI (mpiret); /* create sub-group containing only rank 0 */ reserve_range[0][0] = 0; reserve_range[0][1] = 0; reserve_range[0][2] = 1; mpiret = sc_MPI_Group_range_incl (group, 1, reserve_range, &group_reserve); SC_CHECK_MPI (mpiret); /* create p4est copy and re-partition */ p4est_subcomm = p4est_copy_ext (p4est, 1, 1); (void) p4est_partition_given (p4est_subcomm, partition); /* reduce MPI communicator to non-empty ranks, but keep rank 0 */ sub_exists = p4est_comm_parallel_env_reduce_ext (&p4est_subcomm, group_reserve, 1, NULL); P4EST_ASSERT ((sub_exists && (0 < partition[rank] || rank == 0)) || (!sub_exists && 0 == partition[rank])); if (sub_exists) { /* write vtk: reduced communicator */ p4est_vtk_write_file (p4est_subcomm, NULL, P4EST_STRING "_subcomm_sub3"); /* destroy the p4est that has a reduced MPI communicator */ p4est_destroy (p4est_subcomm); } } mpiret = sc_MPI_Barrier (mpicomm); SC_CHECK_MPI (mpiret); P4EST_GLOBAL_INFOF ("%s: Done test 3\n", this_fn_name); /* * Test 4: Reduce MPI communicator to non-empty ranks, but keep last 2 ranks */ P4EST_GLOBAL_INFOF ("%s: Into test 4\n", this_fn_name); { p4est_t *p4est_subcomm; int sub_exists; sc_MPI_Group group, group_reserve; int reserve_range[1][3]; /* create group of full MPI communicator */ mpiret = sc_MPI_Comm_group (mpicomm, &group); SC_CHECK_MPI (mpiret); /* create sub-group containing only last 2 ranks */ reserve_range[0][0] = SC_MAX (0, mpisize - 2); reserve_range[0][1] = mpisize - 1; reserve_range[0][2] = 1; mpiret = sc_MPI_Group_range_incl (group, 1, reserve_range, &group_reserve); SC_CHECK_MPI (mpiret); /* create p4est copy and re-partition */ p4est_subcomm = p4est_copy_ext (p4est, 1, 1); (void) p4est_partition_given (p4est_subcomm, partition); /* reduce MPI communicator to non-empty ranks, but keep last 2 ranks */ sub_exists = p4est_comm_parallel_env_reduce_ext (&p4est_subcomm, group_reserve, 0, NULL); P4EST_ASSERT ((sub_exists && (0 < partition[rank] || mpisize - 2 <= rank)) || (!sub_exists && 0 == partition[rank])); if (sub_exists) { /* write vtk: reduced communicator */ p4est_vtk_write_file (p4est_subcomm, NULL, P4EST_STRING "_subcomm_sub4"); /* destroy the p4est that has a reduced MPI communicator */ p4est_destroy (p4est_subcomm); } } mpiret = sc_MPI_Barrier (mpicomm); SC_CHECK_MPI (mpiret); P4EST_GLOBAL_INFOF ("%s: Done test 4\n", this_fn_name); /* destroy */ P4EST_FREE (partition); p4est_destroy (p4est); p4est_connectivity_destroy (connectivity); /* finalize */ sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
static int sc_bspline_find_interval (sc_bspline_t * bs, double t) { int i, iguess; double t0, t1; const double *knotse = bs->knots->e[0]; t0 = knotse[bs->n]; t1 = knotse[bs->n + bs->l]; SC_ASSERT (t >= t0 && t <= t1); SC_ASSERT (bs->cacheknot >= bs->n && bs->cacheknot < bs->n + bs->l); if (t >= t1) { iguess = bs->cacheknot = bs->n + bs->l - 1; } else if (knotse[bs->cacheknot] <= t && t < knotse[bs->cacheknot + 1]) { iguess = bs->cacheknot; } else { const int nshift = 1; int ileft, iright; double tleft, tright; ileft = bs->n; iright = bs->n + bs->l - 1; iguess = bs->n + (int) floor ((t - t0) / (t1 - t0) * bs->l); iguess = SC_MAX (iguess, ileft); iguess = SC_MIN (iguess, iright); for (i = 0;; ++i) { tleft = knotse[iguess]; tright = knotse[iguess + 1]; if (t < tleft) { iright = iguess - 1; if (i < nshift) { iguess = iright; } else { iguess = (ileft + iright + 1) / 2; } } else if (t >= tright) { ileft = iguess + 1; if (i < nshift) { iguess = ileft; } else { iguess = (ileft + iright) / 2; } } else { if (i > 0) { SC_LDEBUGF ("For %g needed %d search steps\n", t, i); } break; } } bs->cacheknot = iguess; } SC_ASSERT (iguess >= bs->n && iguess < bs->n + bs->l); SC_CHECK_ABORT ((knotse[iguess] <= t && t < knotse[iguess + 1]) || (t >= t1 && iguess == bs->n + bs->l - 1), "Bug in sc_bspline_find_interval"); return iguess; }
static void p8est_bal_edge_con_internal (p4est_quadrant_t const *q, p4est_quadrant_t * p, int edge, int balance, int *consistent, p4est_quadrant_t * add) { int plevel = p->level; int qlevel = q->level; int blevel; int child; int recon; p4est_quadrant_t porig; p4est_quadrant_t temp; p4est_quadrant_t a; p4est_qcoord_t dx, dy; p4est_qcoord_t dist; p4est_qcoord_t qlen, plen, mask; p4est_qcoord_t b1len, pmask; int i; P4EST_ASSERT (p4est_quadrant_is_extended (q)); P4EST_ASSERT (p4est_quadrant_is_extended (p)); if (qlevel <= plevel) { if (consistent != NULL) { *consistent = 1; } return; } qlen = P4EST_QUADRANT_LEN (qlevel); plen = P4EST_QUADRANT_LEN (plevel); switch (edge / 4) { case 0: dx = (edge & 1) ? (q->y + qlen) - (p->y + plen) : p->y - q->y; dy = (edge & 2) ? (q->z + qlen) - (p->z + plen) : p->z - q->z; break; case 1: dx = (edge & 1) ? (q->x + qlen) - (p->x + plen) : p->x - q->x; dy = (edge & 2) ? (q->z + qlen) - (p->z + plen) : p->z - q->z; break; case 2: dx = (edge & 1) ? (q->x + qlen) - (p->x + plen) : p->x - q->x; dy = (edge & 2) ? (q->y + qlen) - (p->y + plen) : p->y - q->y; break; default: SC_ABORT_NOT_REACHED (); } P4EST_ASSERT (dx >= 0); P4EST_ASSERT (dy >= 0); if (balance) { dist = SC_MAX (dx, dy); blevel = p4est_balance_kernel_1d (dist, qlevel); } else { blevel = p4est_balance_kernel_2d (dx, dy, qlevel); } if (blevel <= plevel) { if (consistent != NULL) { *consistent = 1; } return; } if (consistent != NULL) { *consistent = 0; } porig = *p; *p = *q; switch (edge / 4) { case 0: p->y += (edge & 1) ? -dx : dx; p->z += (edge & 2) ? -dy : dy; break; case 1: p->x += (edge & 1) ? -dx : dx; p->z += (edge & 2) ? -dy : dy; break; case 2: p->x += (edge & 1) ? -dx : dx; p->y += (edge & 2) ? -dy : dy; break; default: SC_ABORT_NOT_REACHED (); } mask = -1 << (P4EST_MAXLEVEL - blevel); p->x &= mask; p->y &= mask; p->z &= mask; p->level = blevel; P4EST_ASSERT (p4est_quadrant_is_extended (p)); if (add != NULL) { add[1] = *p; /* this is the only quad needed if it is only one level smaller than the * original quadrant */ if (blevel == plevel - 1) { return; } mask = -1 << (P4EST_MAXLEVEL - (blevel - 1)); pmask = -1 << (P4EST_MAXLEVEL - (plevel)); a = *p; a.x &= mask; a.y &= mask; a.z &= mask; a.level = blevel - 1; b1len = P4EST_QUADRANT_LEN (blevel - 1); for (i = -1; i <= 1; i += 2) { temp = a; /* temp is in a family group one family group over from temp */ switch (edge / 4) { case 0: temp.x += i * b1len; break; case 1: temp.y += i * b1len; break; case 2: temp.z += i * b1len; break; default: SC_ABORT_NOT_REACHED (); } if ((temp.x & pmask) != porig.x || (temp.y & pmask) != porig.y || (temp.z & pmask) != porig.z) { /* only test other descendents of p */ continue; } child = p8est_edge_corners[edge][(1 - i) / 2]; p4est_bal_corner_con_internal (q, &temp, child, balance, &recon); if (!recon) { add[1 + i] = temp; } } } }
/* \a corner is the corner of \a p closest to \a q: the corner of \a q closest * to \a p is the dual of \a corner */ static void p4est_bal_corner_con_internal (p4est_quadrant_t const *q, p4est_quadrant_t * p, int corner, int balance, int *consistent) { int qlevel = q->level; int plevel = p->level; int blevel; p4est_qcoord_t qlen, plen, mask; p4est_qcoord_t dx, dy, dist; #ifdef P4_TO_P8 p4est_qcoord_t dz; #endif P4EST_ASSERT (p4est_quadrant_is_extended (q)); P4EST_ASSERT (p4est_quadrant_is_extended (p)); if (qlevel <= plevel) { if (consistent != NULL) { *consistent = 1; } return; } qlen = P4EST_QUADRANT_LEN (qlevel); plen = P4EST_QUADRANT_LEN (plevel); dx = (corner & 1) ? ((q->x + qlen) - (p->x + plen)) : p->x - q->x; P4EST_ASSERT (dx >= 0); dy = (corner & 2) ? ((q->y + qlen) - (p->y + plen)) : p->y - q->y; P4EST_ASSERT (dy >= 0); #ifdef P4_TO_P8 dz = (corner & 4) ? ((q->z + qlen) - (p->z + plen)) : p->z - q->z; P4EST_ASSERT (dz >= 0); #endif #ifndef P4_TO_P8 if (balance) { dist = SC_MAX (dx, dy); blevel = p4est_balance_kernel_1d (dist, qlevel); } else { blevel = p4est_balance_kernel_2d (dx, dy, qlevel); } #else switch (balance) { case 0: blevel = p8est_balance_kernel_3d_face (dx, dy, dz, qlevel); break; case 1: blevel = p8est_balance_kernel_3d_edge (dx, dy, dz, qlevel); break; case 2: dist = SC_MAX (dx, dy); dist = SC_MAX (dist, dz); blevel = p4est_balance_kernel_1d (dist, qlevel); break; default: SC_ABORT_NOT_REACHED (); } #endif if (blevel <= plevel) { if (consistent != NULL) { *consistent = 1; } return; } if (consistent != NULL) { *consistent = 0; } mask = -1 << (P4EST_MAXLEVEL - blevel); p->x = q->x + ((corner & 1) ? -dx : dx); p->x &= mask; p->y = q->y + ((corner & 2) ? -dy : dy); p->y &= mask; #ifdef P4_TO_P8 p->z = q->z + ((corner & 4) ? -dz : dz); p->z &= mask; #endif p->level = blevel; P4EST_ASSERT (p4est_quadrant_is_extended (p)); }