void refine_hp ( p4est_iter_volume_info_t* info, void* user_data ) { p4est_quadrant_t* quadrant = info->quad; hp_amr_data_t* hp_amr_data = (hp_amr_data_t*) info->p4est->user_pointer; element_data_t* elem_data = (element_data_t*) info->quad->p.user_data; /* Compute the integer coordinate extent of a quadrant of length 2^(-3). */ const p4est_qcoord_t eighth = P4EST_QUADRANT_LEN (3); /* Compute the length of the current quadrant in integer coordinates. */ const p4est_qcoord_t length = P4EST_QUADRANT_LEN (quadrant->level); /* Refine if the quadrant intersects the block in question. */ int h_refine = ((quadrant->x + length > 5 * eighth && quadrant->x < 6 * eighth) && (quadrant->y + length > 2 * eighth && quadrant->y < 3 * eighth) && #ifdef P4_TO_P8 (quadrant->z + length > 6 * eighth && quadrant->z < 7 * eighth) && #endif 1); int deg = elem_data->deg; if (h_refine == 1){ hp_amr_data->refinement_log[info->quadid] = -deg; } else { hp_amr_data->refinement_log[info->quadid] = util_min_int(deg+1, ((MAX_DEGREE)-1)); } }
/* given two profiles (layers that have been reduced to just their levels), * take the union, i.e. combine them, taking the finer layers */ static void p6est_profile_union (sc_array_t * a, sc_array_t * b, sc_array_t * c) { size_t az, bz, na; P4EST_ASSERT (SC_ARRAY_IS_OWNER (c)); P4EST_ASSERT (a->elem_size == sizeof (int8_t)); P4EST_ASSERT (b->elem_size == sizeof (int8_t)); P4EST_ASSERT (c->elem_size == sizeof (int8_t)); int8_t al, bl, finel, *cc; p4est_qcoord_t finesize, coarsesize; sc_array_t *finer; size_t *fineincr; sc_array_truncate (c); az = 0; bz = 0; na = a->elem_count; while (az < na) { P4EST_ASSERT (bz < b->elem_count); cc = (int8_t *) sc_array_push (c); al = *((int8_t *) sc_array_index (a, az++)); bl = *((int8_t *) sc_array_index (b, bz++)); if (al == bl) { *cc = al; continue; } else if (al > bl) { finer = a; finesize = P4EST_QUADRANT_LEN (al); fineincr = &az; finel = al; coarsesize = P4EST_QUADRANT_LEN (bl); } else { finer = b; finesize = P4EST_QUADRANT_LEN (bl); fineincr = &bz; finel = bl; coarsesize = P4EST_QUADRANT_LEN (al); } P4EST_ASSERT (finesize < coarsesize); do { *cc = finel; cc = (int8_t *) sc_array_push (c); finel = *((int8_t *) sc_array_index (finer, (*fineincr)++)); finesize += P4EST_QUADRANT_LEN (finel); } while (finesize < coarsesize); P4EST_ASSERT (finesize == coarsesize); *cc = finel; } }
static 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--; } } }
static int is_farther (p4est_quadrant_t * orig, p4est_quadrant_t * targ, p4est_quadrant_t * newq) { p4est_qcoord_t ox1, ox2, nx1, nx2; p4est_qcoord_t oy1, oy2, ny1, ny2; #ifdef P4_TO_P8 p4est_qcoord_t oz1, oz2, nz1, nz2; #endif p4est_qcoord_t nl = P4EST_QUADRANT_LEN (newq->level); p4est_qcoord_t tl = P4EST_QUADRANT_LEN (targ->level); P4EST_ASSERT (newq->level == orig->level); ox1 = targ->x - orig->x; ox2 = (orig->x + nl) - (targ->x + tl); nx1 = targ->x - newq->x; nx2 = (newq->x + nl) - (targ->x + tl); if (ox1 > 0 && nx1 > ox1) { return 1; } if (ox2 > 0 && nx2 > ox2) { return 1; } oy1 = targ->y - orig->y; oy2 = (orig->y + nl) - (targ->y + tl); ny1 = targ->y - newq->y; ny2 = (newq->y + nl) - (targ->y + tl); if (oy1 > 0 && ny1 > oy1) { return 1; } if (oy2 > 0 && ny2 > oy2) { return 1; } #ifdef P4_TO_P8 oz1 = targ->z - orig->z; oz2 = (orig->z + nl) - (targ->z + tl); nz1 = targ->z - newq->z; nz2 = (newq->z + nl) - (targ->z + tl); if (oz1 > 0 && nz1 > oz1) { return 1; } if (oz2 > 0 && nz2 > oz2) { return 1; } #endif return 0; }
static int refine_some (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * q) { if (q->x < P4EST_QUADRANT_LEN (2)) { return q->level <= 4; } else if (q->x < P4EST_QUADRANT_LEN (1)) { return q->level <= 3; } else { return q->level <= 2; } }
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; } } }
static int refine_normal (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * quadrant) { if ((int) quadrant->level >= (refine_level - (int) (which_tree % 3))) { return 0; } if (quadrant->level == 1 && p4est_quadrant_child_id (quadrant) == 3) { return 1; } if (quadrant->x == P4EST_LAST_OFFSET (2) && quadrant->y == P4EST_LAST_OFFSET (2)) { return 1; } #ifndef P4_TO_P8 if (quadrant->x >= P4EST_QUADRANT_LEN (2)) { return 0; } #else if (quadrant->z >= P8EST_QUADRANT_LEN (2)) { return 0; } #endif return 1; }
/** Initialize the state variables of incoming quadrants from outgoing * quadrants. * * The functions p4est_refine_ext(), p4est_coarsen_ext(), and * p4est_balance_ext() take as an argument a p4est_replace_t callback function, * which allows one to setup the quadrant data of incoming quadrants from the * data of outgoing quadrants, before the outgoing data is destroyed. This * function matches the p4est_replace_t prototype. * * In this example, we linearly interpolate the state variable of a quadrant * that is refined to its children, and we average the midpoints of children * that are being coarsened to the parent. * * \param [in] p4est the forest * \param [in] which_tree the tree in the forest containing \a children * \param [in] num_outgoing the number of quadrants that are being replaced: * either 1 if a quadrant is being refined, or * P4EST_CHILDREN if a family of children are being * coarsened. * \param [in] outgoing the outgoing quadrants * \param [in] num_incoming the number of quadrants that are being added: * either P4EST_CHILDREN if a quadrant is being refined, or * 1 if a family of children are being * coarsened. * \param [in,out] incoming quadrants whose data are initialized. */ static void step3_replace_quads (p4est_t * p4est, p4est_topidx_t which_tree, int num_outgoing, p4est_quadrant_t * outgoing[], int num_incoming, p4est_quadrant_t * incoming[]) { step3_data_t *parent_data, *child_data; int i, j; double h; double du_old, du_est; if (num_outgoing > 1) { /* this is coarsening */ parent_data = (step3_data_t *) incoming[0]->p.user_data; parent_data->u = 0.; for (j = 0; j < P4EST_DIM; j++) { parent_data->du[j] = (1. / 0.); } for (i = 0; i < P4EST_CHILDREN; i++) { child_data = (step3_data_t *) outgoing[i]->p.user_data; parent_data->u += child_data->u / P4EST_CHILDREN; for (j = 0; j < P4EST_DIM; j++) { du_old = parent_data->du[j]; du_est = child_data->du[j]; if (du_old == du_old) { if (du_est * du_old >= 0.) { if (fabs (du_est) < fabs (du_old)) { parent_data->du[j] = du_est; } } else { parent_data->du[j] = 0.; } } else { parent_data->du[j] = du_est; } } } } else { /* this is refinement */ parent_data = (step3_data_t *) outgoing[0]->p.user_data; h = (double) P4EST_QUADRANT_LEN (outgoing[0]->level) / (double) P4EST_ROOT_LEN; for (i = 0; i < P4EST_CHILDREN; i++) { child_data = (step3_data_t *) incoming[i]->p.user_data; child_data->u = parent_data->u; for (j = 0; j < P4EST_DIM; j++) { child_data->du[j] = parent_data->du[j]; child_data->u += (h / 4.) * parent_data->du[j] * ((i & (1 << j)) ? 1. : -1); } } } }
/** Coarsen by the L2 error estimate of the initial condition. * * Given the maximum global error, we enforce that each quadrant's portion of * the error must not exceed is fraction of the total volume of the domain * (which is 1). * * \param [in] p4est the forest * \param [in] which_tree the tree in the forest containing \a children * \param [in] children a family of quadrants * * \return 1 if \a children should be coarsened, 0 otherwise. */ static int step3_coarsen_initial_condition (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * children[]) { p4est_quadrant_t parent; step3_ctx_t *ctx = (step3_ctx_t *) p4est->user_pointer; double global_err = ctx->max_err; double global_err2 = global_err * global_err; double h; step3_data_t parentdata; double parentmidpoint[3]; double vol, err2; /* get the parent of the first child (the parent of all children) */ p4est_quadrant_parent (children[0], &parent); step3_get_midpoint (p4est, which_tree, &parent, parentmidpoint); parentdata.u = step3_initial_condition (parentmidpoint, parentdata.du, ctx); h = (double) P4EST_QUADRANT_LEN (parent.level) / (double) P4EST_ROOT_LEN; /* the quadrant's volume is also its volume fraction */ #ifdef P4_TO_P8 vol = h * h * h; #else vol = h * h; #endif parent.p.user_data = (void *) (&parentdata); err2 = step3_error_sqr_estimate (&parent); if (err2 < global_err2 * vol) { return 1; } else { return 0; } }
/** Refine by the L2 error estimate. * * Given the maximum global error, we enforce that each quadrant's portion of * the error must not exceed is fraction of the total volume of the domain * (which is 1). * * This function matches the p4est_refine_t prototype that is used by * p4est_refine() and p4est_refine_ext(). * * \param [in] p4est the forest * \param [in] which_tree the tree in the forest containing \a q * \param [in] q the quadrant * * \return 1 if \a q should be refined, 0 otherwise. */ static int step3_refine_err_estimate (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * q) { step3_ctx_t *ctx = (step3_ctx_t *) p4est->user_pointer; double global_err = ctx->max_err; double global_err2 = global_err * global_err; double h = (double) P4EST_QUADRANT_LEN (q->level) / (double) P4EST_ROOT_LEN; double vol, err2; /* the quadrant's volume is also its volume fraction */ #ifdef P4_TO_P8 vol = h * h * h; #else vol = h * h; #endif err2 = step3_error_sqr_estimate (q); if (err2 > global_err2 * vol) { return 1; } else { return 0; } }
/** Estimate the square of the approximation error on a quadrant. * * We compute our estimate by integrating the difference of a constant * approximation at the midpoint and a linear approximation that interpolates * at the midpoint. * * \param [in] q a quadrant * * \return the square of the error estimate for the state variables contained * in \a q's data. */ static double step3_error_sqr_estimate (p4est_quadrant_t * q) { step3_data_t *data = (step3_data_t *) q->p.user_data; int i; double diff2; double *du = data->du; double h = (double) P4EST_QUADRANT_LEN (q->level) / (double) P4EST_ROOT_LEN; double vol; #ifdef P4_TO_P8 vol = h * h * h; #else vol = h * h; #endif diff2 = 0.; /* use the approximate derivative to estimate the L2 error */ for (i = 0; i < P4EST_DIM; i++) { diff2 += du[i] * du[i] * (1. / 12.) * h * h * vol; } return diff2; }
static int coarsen_some (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * q[]) { SC_CHECK_ABORT (p4est_quadrant_is_familypv (q), "Coarsen invocation"); if (q[0]->x < P4EST_QUADRANT_LEN (2)) { return q[0]->level >= 2; } else if (q[0]->x < P4EST_QUADRANT_LEN (1)) { return q[0]->level >= 3; } else { return q[0]->level >= 4; } }
void p8est_quadrant_edge_neighbor (const p4est_quadrant_t * q, int edge, p4est_quadrant_t * r) { const p4est_qcoord_t qh = P4EST_QUADRANT_LEN (q->level); P4EST_ASSERT (0 <= edge && edge < 12); P4EST_ASSERT (p4est_quadrant_is_valid (q)); switch (edge / 4) { case 0: r->x = q->x; r->y = q->y + (2 * (edge & 0x01) - 1) * qh; r->z = q->z + ((edge & 0x02) - 1) * qh; break; case 1: r->x = q->x + (2 * (edge & 0x01) - 1) * qh; r->y = q->y; r->z = q->z + ((edge & 0x02) - 1) * qh; break; case 2: r->x = q->x + (2 * (edge & 0x01) - 1) * qh; r->y = q->y + ((edge & 0x02) - 1) * qh; r->z = q->z; break; default: SC_ABORT_NOT_REACHED (); break; } r->level = q->level; P4EST_ASSERT (p4est_quadrant_is_extended (r)); }
/** Get the coordinates of the midpoint of a quadrant. * * \param [in] p4est the forest * \param [in] which_tree the tree in the forest containing \a q * \param [in] q the quadrant * \param [out] xyz the coordinates of the midpoint of \a q */ static void step3_get_midpoint (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * q, double xyz[3]) { p4est_qcoord_t half_length = P4EST_QUADRANT_LEN (q->level) / 2; p4est_qcoord_to_vertex (p4est->connectivity, which_tree, q->x + half_length, q->y + half_length, #ifdef P4_TO_P8 q->z + half_length, #endif xyz); }
/** Coarsen by the L2 error estimate of the current state approximation. * * Given the maximum global error, we enforce that each quadrant's portion of * the error must not exceed its fraction of the total volume of the domain * (which is 1). * * This function matches the p4est_coarsen_t prototype that is used by * p4est_coarsen() and p4est_coarsen_ext(). * * \param [in] p4est the forest * \param [in] which_tree the tree in the forest containing \a children * \param [in] children a family of quadrants * * \return 1 if \a children should be coarsened, 0 otherwise. */ static int step3_coarsen_err_estimate (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * children[]) { step3_ctx_t *ctx = (step3_ctx_t *) p4est->user_pointer; double global_err = ctx->max_err; double global_err2 = global_err * global_err; double h; step3_data_t *data; double vol, err2, childerr2; double parentu; double diff; int i; h = (double) P4EST_QUADRANT_LEN (children[0]->level) / (double) P4EST_ROOT_LEN; /* the quadrant's volume is also its volume fraction */ #ifdef P4_TO_P8 vol = h * h * h; #else vol = h * h; #endif /* compute the average */ parentu = 0.; for (i = 0; i < P4EST_CHILDREN; i++) { data = (step3_data_t *) children[i]->p.user_data; parentu += data->u / P4EST_CHILDREN; } err2 = 0.; for (i = 0; i < P4EST_CHILDREN; i++) { childerr2 = step3_error_sqr_estimate (children[i]); if (childerr2 > global_err2 * vol) { return 0; } err2 += step3_error_sqr_estimate (children[i]); diff = (parentu - data->u) * (parentu - data->u); err2 += diff * vol; } if (err2 < global_err2 * (vol * P4EST_CHILDREN)) { return 1; } else { return 0; } }
static int refine_fn (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * quadrant) { if (quadrant->level >= 6) { return 0; } #ifdef P4_TO_P8 if (quadrant->level >= 5 && quadrant->z <= P4EST_QUADRANT_LEN (3)) { return 0; } #endif if (quadrant->x == P4EST_LAST_OFFSET (2) && quadrant->y == P4EST_LAST_OFFSET (2)) { return 1; } if (quadrant->x >= P4EST_QUADRANT_LEN (2)) { return 0; } return 1; }
static int refine_fn (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * quadrant) { int cid; if (which_tree == 2 || which_tree == 3) { return 0; } cid = p4est_quadrant_child_id (quadrant); if (cid == P4EST_CHILDREN - 1 || (quadrant->x >= P4EST_LAST_OFFSET (P4EST_MAXLEVEL - 2) && quadrant->y >= P4EST_LAST_OFFSET (P4EST_MAXLEVEL - 2) #ifdef P4_TO_P8 && quadrant->z >= P4EST_LAST_OFFSET (P4EST_MAXLEVEL - 2) #endif )) { return 1; } if ((int) quadrant->level >= (refine_level - (int) (which_tree % 3))) { return 0; } if (quadrant->level == 1 && cid == 2) { return 1; } if (quadrant->x == P4EST_QUADRANT_LEN (2) && quadrant->y == P4EST_LAST_OFFSET (2)) { return 1; } if (quadrant->y >= P4EST_QUADRANT_LEN (2)) { return 0; } return 1; }
/** Compute the new value of the state from the computed time derivative. * * We use a simple forward Euler scheme. * * The derivative was computed by a p4est_iterate() loop by the callbacks * step3_quad_divergence() and step3_upwind_flux(). Now we multiply this by * the timestep and add to the current solution. * * 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] user_data the user_data given to p4est_iterate(): in this case, * it points to the timestep. */ static void step3_timestep_update (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 dt = *((double *) user_data); double vol; double h = (double) P4EST_QUADRANT_LEN (q->level) / (double) P4EST_ROOT_LEN; #ifdef P4_TO_P8 vol = h * h * h; #else vol = h * h; #endif data->u += dt * data->dudt / vol; }
int p8est_quadrant_touches_edge (const p4est_quadrant_t * q, int edge, int inside) { int quad_contact[P4EST_FACES]; int axis, side, incount; p4est_qcoord_t lower, upper; P4EST_ASSERT (0 <= edge && edge < 12); axis = edge / 4; if (q->level == P4EST_MAXLEVEL) { P4EST_ASSERT (p4est_quadrant_is_node (q, inside)); lower = 0; upper = P4EST_ROOT_LEN - (int) inside; } else { if (!inside) { P4EST_ASSERT (p4est_quadrant_is_extended (q)); lower = -P4EST_QUADRANT_LEN (q->level); upper = P4EST_ROOT_LEN; } else { P4EST_ASSERT (p4est_quadrant_is_valid (q)); lower = 0; upper = P4EST_LAST_OFFSET (q->level); } } quad_contact[0] = (q->x == lower); quad_contact[1] = (q->x == upper); quad_contact[2] = (q->y == lower); quad_contact[3] = (q->y == upper); quad_contact[4] = (q->z == lower); quad_contact[5] = (q->z == upper); incount = 0; if (axis != 0) { side = edge & 1; incount += quad_contact[side]; } if (axis != 1) { side = (axis == 0) ? (edge & 1) : ((edge >> 1) & 1); incount += quad_contact[2 + side]; }
static int refine_fn (p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t * quadrant) { if (quadrant->level >= (refine_level - (which_tree % 3))) { return 0; } if (quadrant->level == 1 && p4est_quadrant_child_id (quadrant) == 3) { return 1; } if (quadrant->x == P4EST_LAST_OFFSET (2) && quadrant->y == P4EST_LAST_OFFSET (2)) { return 1; } if (quadrant->x >= P4EST_QUADRANT_LEN (2)) { return 0; } return 1; }
/** 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 p4est_quadrant_is_family (const p4est_quadrant_t * q0, const p4est_quadrant_t * q1, const p4est_quadrant_t * q2, const p4est_quadrant_t * q3, const p4est_quadrant_t * q4, const p4est_quadrant_t * q5, const p4est_quadrant_t * q6, const p4est_quadrant_t * q7) { const int8_t level = q0->level; p4est_qcoord_t inc; P4EST_ASSERT (p4est_quadrant_is_extended (q0)); P4EST_ASSERT (p4est_quadrant_is_extended (q1)); P4EST_ASSERT (p4est_quadrant_is_extended (q2)); P4EST_ASSERT (p4est_quadrant_is_extended (q3)); P4EST_ASSERT (p4est_quadrant_is_extended (q4)); P4EST_ASSERT (p4est_quadrant_is_extended (q5)); P4EST_ASSERT (p4est_quadrant_is_extended (q6)); P4EST_ASSERT (p4est_quadrant_is_extended (q7)); if (level == 0 || level != q1->level || level != q2->level || level != q3->level || level != q4->level || level != q5->level || level != q6->level || level != q7->level) { return 0; } inc = P4EST_QUADRANT_LEN (level); return ((q0->x + inc == q1->x && q0->y == q1->y && q0->z == q1->z) && (q0->x == q2->x && q0->y + inc == q2->y && q0->z == q2->z) && (q1->x == q3->x && q2->y == q3->y && q0->z == q3->z) && (q0->x == q4->x && q0->y == q4->y && q0->z + inc == q4->z) && (q1->x == q5->x && q1->y == q5->y && q4->z == q5->z) && (q2->x == q6->x && q2->y == q6->y && q4->z == q6->z) && (q3->x == q7->x && q3->y == q7->y && q4->z == q7->z)); }
/** Callback function for interpolating the solution from quadrant midpoints to * corners. * * The function p4est_iterate() takes as an argument a p4est_iter_volume_t * callback function, which it executes at every local quadrant (see * p4est_iterate.h). This function matches the p4est_iter_volume_t prototype. * * In this example, we use the callback function to interpolate the state * variable to the corners, and write those corners into an array so that they * can be written out. * * \param [in] info the information about this quadrant that has been * populated by p4est_iterate() * \param [in,out] user_data the user_data that was given as an argument to * p4est_iterate: in this case, it points to the * array of corner values that we want to write. * The values for the corner of the quadrant * described by \a info are written during the * execution of the callback. */ static void step3_interpolate_solution (p4est_iter_volume_info_t * info, void *user_data) { double *u_interp = (double *) user_data; /* we passed the array of values to fill as the user_data in the call to p4est_iterate */ p4est_t *p4est = info->p4est; p4est_quadrant_t *q = info->quad; p4est_topidx_t which_tree = info->treeid; p4est_locidx_t local_id = info->quadid; /* this is the index of q *within its tree's numbering*. We want to convert it its index for all the quadrants on this process, which we do below */ p4est_tree_t *tree; step3_data_t *data = (step3_data_t *) q->p.user_data; double h; p4est_locidx_t arrayoffset; double this_u; int i, j; tree = p4est_tree_array_index (p4est->trees, which_tree); local_id += tree->quadrants_offset; /* now the id is relative to the MPI process */ arrayoffset = P4EST_CHILDREN * local_id; /* each local quadrant has 2^d (P4EST_CHILDREN) values in u_interp */ h = (double) P4EST_QUADRANT_LEN (q->level) / (double) P4EST_ROOT_LEN; for (i = 0; i < P4EST_CHILDREN; i++) { this_u = data->u; /* loop over the derivative components and linearly interpolate from the * midpoint to the corners */ for (j = 0; j < P4EST_DIM; j++) { /* In order to know whether the direction from the midpoint to the corner is * negative or positive, we take advantage of the fact that the corners * are in z-order. If i is an odd number, it is on the +x side; if it * is even, it is on the -x side. If (i / 2) is an odd number, it is on * the +y side, etc. */ this_u += (h / 2) * data->du[j] * ((i & (1 << j)) ? 1. : -1.); } u_interp[arrayoffset + i] = this_u; } }
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 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; }
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); }
/** For two quadrants on either side of a face, estimate the derivative normal * to the face. * * This function matches the p4est_iter_face_t prototype used by * p4est_iterate(). * * \param [in] info the information about this quadrant that has been * populated by p4est_iterate() * \param [in] user_data the user_data given to p4est_iterate(): in this case, * it points to the ghost_data array, which contains the * step3_data_t data for all of the ghost cells, which * was populated by p4est_ghost_exchange_data() */ static void step3_minmod_estimate (p4est_iter_face_info_t * info, void *user_data) { int i, j; p4est_iter_face_side_t *side[2]; sc_array_t *sides = &(info->sides); step3_data_t *ghost_data = (step3_data_t *) user_data; step3_data_t *udata; p4est_quadrant_t *quad; double uavg[2]; double h[2]; double du_est, du_old; int which_dir; /* because there are no boundaries, every face has two sides */ P4EST_ASSERT (sides->elem_count == 2); side[0] = p4est_iter_fside_array_index_int (sides, 0); side[1] = p4est_iter_fside_array_index_int (sides, 1); which_dir = side[0]->face / 2; /* 0 == x, 1 == y, 2 == z */ for (i = 0; i < 2; i++) { uavg[i] = 0; if (side[i]->is_hanging) { /* there are 2^(d-1) (P4EST_HALF) subfaces */ for (j = 0; j < P4EST_HALF; j++) { quad = side[i]->is.hanging.quad[j]; h[i] = (double) P4EST_QUADRANT_LEN (quad->level) / (double) P4EST_ROOT_LEN; if (side[i]->is.hanging.is_ghost[j]) { udata = &ghost_data[side[i]->is.hanging.quadid[j]]; } else { udata = (step3_data_t *) side[i]->is.hanging.quad[j]->p.user_data; } uavg[i] += udata->u; } uavg[i] /= P4EST_HALF; } else { quad = side[i]->is.full.quad; h[i] = (double) P4EST_QUADRANT_LEN (quad->level) / (double) P4EST_ROOT_LEN; if (side[i]->is.full.is_ghost) { udata = &ghost_data[side[i]->is.full.quadid]; } else { udata = (step3_data_t *) side[i]->is.full.quad->p.user_data; } uavg[i] = udata->u; } } du_est = (uavg[1] - uavg[0]) / ((h[0] + h[1]) / 2.); for (i = 0; i < 2; i++) { if (side[i]->is_hanging) { /* there are 2^(d-1) (P4EST_HALF) subfaces */ for (j = 0; j < P4EST_HALF; j++) { quad = side[i]->is.hanging.quad[j]; if (!side[i]->is.hanging.is_ghost[j]) { udata = (step3_data_t *) quad->p.user_data; du_old = udata->du[which_dir]; if (du_old == du_old) { /* there has already been an update */ if (du_est * du_old >= 0.) { if (fabs (du_est) < fabs (du_old)) { udata->du[which_dir] = du_est; } } else { udata->du[which_dir] = 0.; } } else { udata->du[which_dir] = du_est; } } } } else { quad = side[i]->is.full.quad; if (!side[i]->is.full.is_ghost) { udata = (step3_data_t *) quad->p.user_data; du_old = udata->du[which_dir]; if (du_old == du_old) { /* there has already been an update */ if (du_est * du_old >= 0.) { if (fabs (du_est) < fabs (du_old)) { udata->du[which_dir] = du_est; } } else { udata->du[which_dir] = 0.; } } else { udata->du[which_dir] = du_est; } } } } }
int main (int argc, char **argv) { p4est_quadrant_t root; p4est_quadrant_t p; p4est_quadrant_t q; p4est_quadrant_t desc; int face, corner; #ifndef P4_TO_P8 int maxlevel = 9; #else int edge; int maxlevel = 6; #endif int mpiret, mpisize, mpirank; sc_MPI_Comm mpicomm; uint64_t i, ifirst, ilast; int level; sc_array_t *seeds, *seeds_check; int testval; int checkval; int j, nrand = 1000; /* 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); srandom (9212007); sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT); p4est_init (NULL, SC_LP_DEFAULT); seeds = sc_array_new (sizeof (p4est_quadrant_t)); seeds_check = sc_array_new (sizeof (p4est_quadrant_t)); memset (&root, 0, sizeof (p4est_quadrant_t)); root.level = 2; root.x = P4EST_QUADRANT_LEN (2); root.y = P4EST_QUADRANT_LEN (2); #ifdef P4_TO_P8 root.z = P4EST_QUADRANT_LEN (2); #endif P4EST_QUADRANT_INIT (&p); P4EST_QUADRANT_INIT (&q); #if 1 for (face = 0; face < P4EST_FACES; face++) { p4est_quadrant_face_neighbor (&root, face ^ 1, &p); P4EST_GLOBAL_VERBOSEF ("Testing face %d\n", face); for (level = 4; level <= maxlevel; level++) { P4EST_GLOBAL_VERBOSEF (" level %d\n", level); p4est_quadrant_first_descendant (&root, &desc, level); ifirst = p4est_quadrant_linear_id (&desc, level); p4est_quadrant_last_descendant (&root, &desc, level); ilast = p4est_quadrant_linear_id (&desc, level); for (i = ifirst; i <= ilast; i += P4EST_CHILDREN) { p4est_quadrant_set_morton (&q, level, i); #ifndef P4_TO_P8 testval = p4est_balance_seeds_face (&q, &p, face, P4EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p4est_balance_seeds_face error"); compare_seeds (seeds, seeds_check); #else testval = p4est_balance_seeds_face (&q, &p, face, P8EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_face error"); compare_seeds (seeds, seeds_check); testval = p4est_balance_seeds_face (&q, &p, face, P8EST_CONNECT_EDGE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_face error"); compare_seeds (seeds, seeds_check); #endif testval = p4est_balance_seeds_face (&q, &p, face, P4EST_CONNECT_FULL, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FULL, seeds_check); SC_CHECK_ABORT (testval == checkval, "p4est_balance_seeds_face error"); compare_seeds (seeds, seeds_check); } } if (!face) { P4EST_GLOBAL_VERBOSE (" random levels\n"); for (j = 0; j < (int) nrand; j++) { level = ((random ()) % (P4EST_QMAXLEVEL - maxlevel)) + maxlevel + 1; p4est_quadrant_first_descendant (&root, &desc, level); ifirst = p4est_quadrant_linear_id (&desc, level); p4est_quadrant_last_descendant (&root, &desc, level); ilast = p4est_quadrant_linear_id (&desc, level); i = ((random ()) % (ilast + 1 - ifirst)) + ifirst; p4est_quadrant_set_morton (&q, level, i); #ifndef P4_TO_P8 testval = p4est_balance_seeds_face (&q, &p, face, P4EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p4est_balance_seeds_face error"); compare_seeds (seeds, seeds_check); #else testval = p4est_balance_seeds_face (&q, &p, face, P8EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_face error"); compare_seeds (seeds, seeds_check); testval = p4est_balance_seeds_face (&q, &p, face, P8EST_CONNECT_EDGE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_face error"); compare_seeds (seeds, seeds_check); #endif testval = p4est_balance_seeds_face (&q, &p, face, P4EST_CONNECT_FULL, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FULL, seeds_check); SC_CHECK_ABORT (testval == checkval, "p4est_balance_seeds_face error"); compare_seeds (seeds, seeds_check); } } } #ifdef P4_TO_P8 for (edge = 0; edge < P8EST_EDGES; edge++) { p8est_quadrant_edge_neighbor (&root, edge ^ 3, &p); P4EST_GLOBAL_VERBOSEF ("Testing edge %d\n", edge); for (level = 4; level <= maxlevel; level++) { P4EST_GLOBAL_VERBOSEF (" level %d\n", level); p4est_quadrant_first_descendant (&root, &desc, level); ifirst = p4est_quadrant_linear_id (&desc, level); p4est_quadrant_last_descendant (&root, &desc, level); ilast = p4est_quadrant_linear_id (&desc, level); for (i = ifirst; i <= ilast; i += P4EST_CHILDREN) { p4est_quadrant_set_morton (&q, level, i); testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_edge error"); compare_seeds (seeds, seeds_check); testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_EDGE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_edge error"); compare_seeds (seeds, seeds_check); testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_FULL, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FULL, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_edge error"); compare_seeds (seeds, seeds_check); } } if (!edge) { P4EST_GLOBAL_VERBOSE (" random levels\n"); for (j = 0; j < (int) nrand; j++) { level = ((random ()) % (P4EST_QMAXLEVEL - maxlevel)) + maxlevel + 1; p4est_quadrant_first_descendant (&root, &desc, level); ifirst = p4est_quadrant_linear_id (&desc, level); p4est_quadrant_last_descendant (&root, &desc, level); ilast = p4est_quadrant_linear_id (&desc, level); i = ((random ()) % (ilast + 1 - ifirst)) + ifirst; p4est_quadrant_set_morton (&q, level, i); testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_edge error"); compare_seeds (seeds, seeds_check); testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_EDGE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_edge error"); compare_seeds (seeds, seeds_check); testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_FULL, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FULL, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_edge error"); compare_seeds (seeds, seeds_check); } } } #endif #endif for (corner = 0; corner < P4EST_FACES; corner++) { p4est_quadrant_corner_neighbor (&root, corner ^ (P4EST_CHILDREN - 1), &p); P4EST_GLOBAL_VERBOSEF ("Testing corner %d\n", corner); for (level = 4; level <= maxlevel; level++) { P4EST_GLOBAL_VERBOSEF (" level %d\n", level); p4est_quadrant_first_descendant (&root, &desc, level); ifirst = p4est_quadrant_linear_id (&desc, level); p4est_quadrant_last_descendant (&root, &desc, level); ilast = p4est_quadrant_linear_id (&desc, level); for (i = ifirst; i <= ilast; i += P4EST_CHILDREN) { p4est_quadrant_set_morton (&q, level, i); #ifndef P4_TO_P8 testval = p4est_balance_seeds_corner (&q, &p, corner, P4EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p4est_balance_seeds_corner error"); compare_seeds (seeds, seeds_check); #else testval = p4est_balance_seeds_corner (&q, &p, corner, P8EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_corner error"); compare_seeds (seeds, seeds_check); testval = p4est_balance_seeds_corner (&q, &p, corner, P8EST_CONNECT_EDGE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_corner error"); compare_seeds (seeds, seeds_check); #endif testval = p4est_balance_seeds_corner (&q, &p, corner, P4EST_CONNECT_FULL, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FULL, seeds_check); SC_CHECK_ABORT (testval == checkval, "p4est_balance_seeds_corner error"); compare_seeds (seeds, seeds_check); } } if (!corner) { P4EST_GLOBAL_VERBOSE (" random levels\n"); for (j = 0; j < (int) nrand; j++) { level = ((random ()) % (P4EST_QMAXLEVEL - maxlevel)) + maxlevel + 1; p4est_quadrant_first_descendant (&root, &desc, level); ifirst = p4est_quadrant_linear_id (&desc, level); p4est_quadrant_last_descendant (&root, &desc, level); ilast = p4est_quadrant_linear_id (&desc, level); i = ((random ()) % (ilast + 1 - ifirst)) + ifirst; p4est_quadrant_set_morton (&q, level, i); #ifndef P4_TO_P8 testval = p4est_balance_seeds_corner (&q, &p, corner, P4EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p4est_balance_seeds_corner error"); compare_seeds (seeds, seeds_check); #else testval = p4est_balance_seeds_corner (&q, &p, corner, P8EST_CONNECT_FACE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_corner error"); compare_seeds (seeds, seeds_check); testval = p4est_balance_seeds_corner (&q, &p, corner, P8EST_CONNECT_EDGE, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE, seeds_check); SC_CHECK_ABORT (testval == checkval, "p8est_balance_seeds_corner error"); compare_seeds (seeds, seeds_check); #endif testval = p4est_balance_seeds_corner (&q, &p, corner, P4EST_CONNECT_FULL, seeds); standard_seeds (seeds); checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FULL, seeds_check); SC_CHECK_ABORT (testval == checkval, "p4est_balance_seeds_corner error"); compare_seeds (seeds, seeds_check); } } } sc_array_destroy (seeds); sc_array_destroy (seeds_check); sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
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); }
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; }