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)); }
/** For a quadrant that touches a tree face with a corner inside the face, * get the number of the touching face. */ static int tree_face_quadrant_corner_face (const p4est_quadrant_t * q, int corner) { int which; p4est_qcoord_t end = P4EST_LAST_OFFSET (q->level); P4EST_ASSERT (p4est_quadrant_is_valid (q)); P4EST_ASSERT (0 <= corner && corner < P4EST_CHILDREN); which = corner & 1; if (q->x == (which ? end : 0)) { return which; } which = corner & 2; if (q->y == (which ? end : 0)) { return 2 + (which >> 1); } #ifdef P4_TO_P8 which = corner & 4; if (q->z == (which ? end : 0)) { return 4 + (which >> 2); } #endif SC_ABORT_NOT_REACHED (); }
static void d4est_geometry_compact_disk_X(p4est_geometry_t * geom, p4est_topidx_t which_tree, const double rst[3], double xyz[3]) { double* radii = (double*)geom->user; double R0 = radii[0]; double R1 = radii[1]; double xref = rst[0]; double yref = rst[1]; double x,y; if (which_tree == 0){ /* bottom */ d4est_geometry_compact_disk_map_cube_to_slab(yref, xref, 1., 0., -R1, -R0/sqrt(2), &y, &x); x *= -1.; } else if (which_tree == 1){ /* left */ d4est_geometry_compact_disk_map_cube_to_slab(xref, yref, 1., 0., -R1, -R0/sqrt(2), &x, &y); y *= -1; } else if (which_tree == 2){ /* center */ d4est_geometry_compact_disk_linear_map(xref, 0., 1., -R0/sqrt(2), R0/sqrt(2), &x); d4est_geometry_compact_disk_linear_map(yref, 0., 1., -R0/sqrt(2), R0/sqrt(2), &y); } else if (which_tree == 3){ /* right */ d4est_geometry_compact_disk_map_cube_to_slab(xref, yref, 0, 1, R0/sqrt(2), R1, &x, &y); } else if (which_tree == 4){ /* top */ d4est_geometry_compact_disk_map_cube_to_slab(yref, xref, 0, 1, R0/sqrt(2), R1, &y, &x); } else{ SC_ABORT_NOT_REACHED(); } z xyz[0] = x; xyz[1] = y; xyz[2] = 0.; /* compactify */ if (which_tree != 2){ double xnc = xyz[0]; double ync = xyz[1]; double R = sqrt(xnc*xnc + ync*ync); double r = (R1 + (w - R1)*(R - R1)/(R2 - R1))/(1 - (R - R1)*(1 - w/Rinf)/(R2 - R1)); xyz[0] = r*xnc/R; xyz[1] = r*ync/R; } }
const char * p8est_connect_type_string (p8est_connect_type_t btype) { switch (btype) { case P8EST_CONNECT_FACE: return "FACE"; case P8EST_CONNECT_EDGE: return "EDGE"; case P8EST_CONNECT_CORNER: return "CORNER"; default: SC_ABORT_NOT_REACHED (); } }
int p8est_connect_type_int (p8est_connect_type_t btype) { switch (btype) { case P8EST_CONNECT_FACE: return 1; case P8EST_CONNECT_EDGE: return 2; case P8EST_CONNECT_CORNER: return 3; default: SC_ABORT_NOT_REACHED (); } }
int p8est_quadrant_is_outside_edge_extra (const p4est_quadrant_t * q, int *edge) { int quad_contact[P4EST_FACES]; int face_axis[P4EST_DIM]; P4EST_ASSERT (q->level <= P4EST_QMAXLEVEL); quad_contact[0] = (int) (q->x < 0); quad_contact[1] = (int) (q->x >= P4EST_ROOT_LEN); quad_contact[2] = (int) (q->y < 0); quad_contact[3] = (int) (q->y >= P4EST_ROOT_LEN); quad_contact[4] = (int) (q->z < 0); quad_contact[5] = (int) (q->z >= P4EST_ROOT_LEN); face_axis[0] = quad_contact[0] || quad_contact[1]; face_axis[1] = quad_contact[2] || quad_contact[3]; face_axis[2] = quad_contact[4] || quad_contact[5]; if (face_axis[0] + face_axis[1] + face_axis[2] != 2) { return 0; } if (edge != NULL) { if (!face_axis[0]) { *edge = 0 + 2 * quad_contact[5] + quad_contact[3]; } else if (!face_axis[1]) { *edge = 4 + 2 * quad_contact[5] + quad_contact[1]; } else if (!face_axis[2]) { *edge = 8 + 2 * quad_contact[3] + quad_contact[1]; } else { SC_ABORT_NOT_REACHED (); } P4EST_ASSERT (p8est_quadrant_touches_edge (q, *edge, 0)); } return 1; }
static void p4est_build_verify_4 (p4est_t * p4est) { p4est_topidx_t jt; p4est_locidx_t il, c1, c2; p4est_tree_t *tree; p4est_quadrant_t *quadrant; test_build_t *tb; tb = (test_build_t *) p4est->user_pointer; c1 = c2 = 0; for (jt = p4est->first_local_tree; jt <= p4est->last_local_tree; ++jt) { tree = p4est_tree_array_index (p4est->trees, jt); for (il = 0; il < (p4est_locidx_t) tree->quadrants.elem_count; ++il) { quadrant = p4est_quadrant_array_index (&tree->quadrants, il); switch (*(long *) quadrant->p.user_data) { case 11321: ++c1; break; case -748: ++c2; break; default: SC_ABORT_NOT_REACHED (); } } } SC_CHECK_ABORT (c1 + c2 == p4est->local_num_quadrants, "Test 4 count quadrants"); SC_CHECK_ABORT (c1 + c2 >= (p4est_locidx_t) tb->count_add, "Test 4 count sum"); SC_CHECK_ABORT (c1 == (p4est_locidx_t) tb->init_default, "Test 4 count default"); SC_CHECK_ABORT (c2 == (p4est_locidx_t) tb->init_add, "Test 4 count add"); }
int p4est_balance_seeds (p4est_quadrant_t * q, p4est_quadrant_t * p, p4est_connect_type_t balance, sc_array_t * seeds) { int outside[P4EST_DIM]; int i; int type = 0; p4est_qcoord_t diff; p4est_qcoord_t qc, pc; p4est_qcoord_t pdist = P4EST_QUADRANT_LEN (p->level); p4est_qcoord_t qdist = P4EST_QUADRANT_LEN (q->level); p4est_quadrant_t *s; int f, c; #ifdef P4_TO_P8 int e; #endif if (seeds != NULL) { sc_array_resize (seeds, 0); } /* basic level comparison */ if (q->level <= p->level + 1) { return 0; } for (i = 0; i < P4EST_DIM; i++) { switch (i) { case 0: qc = q->x; pc = p->x; break; case 1: qc = q->y; pc = p->y; break; #ifdef P4_TO_P8 case 2: qc = q->z; pc = p->z; break; #endif default: SC_ABORT_NOT_REACHED (); break; } outside[i] = 0; if (qc < pc) { diff = pc - qc; /* insulation layer comparison */ if (diff > pdist) { return 0; } outside[i] = -1; } else { diff = (qc + qdist) - (pc + pdist); /* insulation layer comparison */ if (diff > pdist) { return 0; } if (diff > 0) { outside[i] = 1; } } type += (outside[i] ? 1 : 0); } switch (type) { case 0: /* q is inside p, so it is its own seed */ sc_array_resize (seeds, seeds->elem_count + 1); s = p4est_quadrant_array_index (seeds, seeds->elem_count - 1); *s = *q; return 1; case 1: for (i = 0; i < P4EST_DIM; i++) { if (outside[i]) { f = 2 * i + (outside[i] > 0 ? 1 : 0); return p4est_balance_seeds_face (q, p, f, balance, seeds); } } SC_ABORT_NOT_REACHED (); return -1; case P4EST_DIM: c = 0; for (i = 0; i < P4EST_DIM; i++) { c += (outside[i] > 0 ? (1 << i) : 0); } return p4est_balance_seeds_corner (q, p, c, balance, seeds); #ifdef P4_TO_P8 case 2: e = 0; c = 0; for (i = 2; i >= 0; i--) { if (outside[i]) { c <<= 1; c |= (outside[i] > 0 ? 1 : 0); } else { e |= (i << 2); } } e |= c; return p8est_balance_seeds_edge (q, p, e, balance, seeds); #endif default: SC_ABORT_NOT_REACHED (); return -1; } }
static void 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; } } } }
static void p4est_bal_face_con_internal (p4est_quadrant_t const *q, p4est_quadrant_t * p, int face, int balance, int *consistent, p4est_quadrant_t * add) { int qlevel = q->level; int plevel = p->level; int blevel; int child; #ifdef P4_TO_P8 int edge; int dual; int achild = -1; #endif int recon; p4est_quadrant_t porig; p4est_quadrant_t temp; p4est_quadrant_t a; int i; #ifndef P4_TO_P8 int nconextra = 3; #else int nconextra = 9; int j; p4est_qcoord_t b2mask; #endif p4est_qcoord_t distance; p4est_qcoord_t qlen, plen, mask, pmask; p4est_qcoord_t b1len; 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 (face) { case 0: distance = p->x - q->x; break; case 1: distance = (q->x + qlen) - (p->x + plen); break; case 2: distance = p->y - q->y; break; case 3: distance = (q->y + qlen) - (p->y + plen); break; #ifdef P4_TO_P8 case 4: distance = p->z - q->z; break; case 5: distance = (q->z + qlen) - (p->z + plen); break; #endif default: SC_ABORT_NOT_REACHED (); } P4EST_ASSERT (distance >= 0); blevel = p4est_balance_kernel_1d (distance, q->level); if (blevel <= plevel) { if (consistent != NULL) { *consistent = 1; } return; } if (consistent != NULL) { *consistent = 0; } porig = *p; *p = *q; /* shift a until it is inside p */ switch (face) { case 0: p->x += distance; break; case 1: p->x -= distance; break; case 2: p->y += distance; break; case 3: p->y -= distance; break; #ifdef P4_TO_P8 case 4: p->z += distance; break; case 5: p->z -= distance; break; #endif default: SC_ABORT_NOT_REACHED (); } mask = -1 << (P4EST_MAXLEVEL - blevel); p->x &= mask; p->y &= mask; #ifdef P4_TO_P8 p->z &= mask; #endif p->level = blevel; P4EST_ASSERT (p4est_quadrant_is_extended (p)); if (add != NULL) { add[nconextra / 2] = *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; #ifdef P4_TO_P8 a.z &= mask; #endif a.level = blevel - 1; b1len = P4EST_QUADRANT_LEN (blevel - 1); #ifndef P4_TO_P8 for (i = -1; i <= 1; i += 2) { temp = a; /* temp is in a family group one family group over from temp */ if (face / 2 == 0) { temp.y += i * b1len; } else { temp.x += i * b1len; } if ((temp.x & pmask) != porig.x || (temp.y & pmask) != porig.y) { /* only test other descendents of p */ continue; } child = p4est_face_corners[face][(1 - i) / 2]; p4est_bal_corner_con_internal (q, &temp, child, balance, &recon); if (!recon) { add[1 + i] = temp; } } #else b2mask = -1 << (P4EST_MAXLEVEL - (blevel - 2)); if (!balance) { achild = p8est_quadrant_child_id (&a); } for (j = -1; j <= 1; j++) { for (i = -1; i <= 1; i++) { if (!i & !j) { continue; } temp = a; switch (face / 2) { case 0: temp.y += i * b1len; temp.z += j * b1len; break; case 1: temp.x += i * b1len; temp.z += j * b1len; break; case 2: temp.x += i * b1len; temp.y += j * 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; } if (i && j) { child = p8est_face_corners[face][(1 - j) + (1 - i) / 2]; /* for face only balance, we need to check a larger neighbor in one * instance */ if (!balance) { dual = p8est_face_corners[face][(1 + j) + (1 + i) / 2]; if (achild == dual) { temp.x &= b2mask; temp.y &= b2mask; temp.z &= b2mask; temp.level = blevel - 2; } } p4est_bal_corner_con_internal (q, &temp, child, balance, &recon); if (!recon) { add[4 + 3 * j + i] = temp; } } else { if (!i) { edge = p8est_face_edges[face][(1 - j) / 2]; } else { edge = p8est_face_edges[face][2 + (1 - i) / 2]; } p8est_bal_edge_con_internal (q, &temp, edge, balance, &recon, NULL); if (!recon) { add[4 + 3 * j + i] = temp; } } } } if (!balance) { for (j = -1; j <= 1; j += 2) { for (i = -1; i <= 1; i += 2) { if (add[4 + 3 * j + i].level != -1 && add[4 + 3 * j + i].level < blevel) { if (add[4 + 3 * j].level != -1 || add[4 + i].level != -1) { memset (&(add[4 + 3 * j + i]), -1, sizeof (p4est_quadrant_t)); } } } } } #endif } }
/* \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)); }