Пример #1
0
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));
  }
}
Пример #2
0
/* 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;
  }
}
Пример #3
0
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--;
    }
  }
}
Пример #4
0
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;

}
Пример #5
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;
  }
}
Пример #6
0
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;
    }
  }
}
Пример #7
0
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;
}
Пример #8
0
/** 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);
      }
    }
  }
}
Пример #9
0
/** 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;
  }
}
Пример #10
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;
  }
}
Пример #11
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;
}
Пример #12
0
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;
  }
}
Пример #13
0
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));
}
Пример #14
0
/** 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);
}
Пример #15
0
/** 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;
  }
}
Пример #16
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;
}
Пример #17
0
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;
}
Пример #18
0
/** 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;
}
Пример #19
0
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];
  }
Пример #20
0
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;
}
Пример #21
0
/** 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;
}
Пример #22
0
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));
}
Пример #23
0
/** 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;
  }

}
Пример #24
0
int
main (int argc, char **argv)
{
  const p4est_qcoord_t qone = 1;
  int                 mpiret;
  int                 k;
  int                 level, mid, cid;
  int                 id0, id1, id2, id3;
  int64_t             index1, index2;
  size_t              iz, jz, incount;
  p4est_qcoord_t      mh = P4EST_QUADRANT_LEN (P4EST_QMAXLEVEL);
  p4est_connectivity_t *connectivity;
  p4est_t            *p4est1;
  p4est_t            *p4est2;
  p4est_tree_t       *t1, *t2, tree;
  p4est_quadrant_t   *p, *q1, *q2;
  p4est_quadrant_t    r, s;
  p4est_quadrant_t    c0, c1, c2, c3;
  p4est_quadrant_t    cv[P4EST_CHILDREN], *cp[P4EST_CHILDREN];
  p4est_quadrant_t    A, B, C, D, E, F, G, H, I, P, Q;
  p4est_quadrant_t    a, f, g, h;
  uint64_t            Aid, Fid;

  /* initialize MPI */
  mpiret = sc_MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);

  /* create connectivity and forest structures */
  connectivity = p4est_connectivity_new_unitsquare ();
  p4est1 = p4est_new_ext (sc_MPI_COMM_SELF, connectivity, 15, 0, 0,
                          0, NULL, NULL);
  p4est2 = p4est_new_ext (sc_MPI_COMM_SELF, connectivity, 15, 0, 0,
                          8, NULL, NULL);

  /* refine the second tree to a uniform level */
  p4est_refine (p4est1, 1, refine_none, NULL);
  p4est_refine (p4est2, 1, refine_some, NULL);
  t1 = p4est_tree_array_index (p4est1->trees, 0);
  t2 = p4est_tree_array_index (p4est2->trees, 0);
  SC_CHECK_ABORT (p4est_tree_is_sorted (t1), "is_sorted");
  SC_CHECK_ABORT (p4est_tree_is_sorted (t2), "is_sorted");

  /* run a bunch of cross-tests */
  p = NULL;
  for (iz = 0; iz < t1->quadrants.elem_count; ++iz) {
    q1 = p4est_quadrant_array_index (&t1->quadrants, iz);

    /* test the index conversion */
    index1 = p4est_quadrant_linear_id (q1, (int) q1->level);
    p4est_quadrant_set_morton (&r, (int) q1->level, index1);
    index2 = p4est_quadrant_linear_id (&r, (int) r.level);
    SC_CHECK_ABORT (index1 == index2, "index conversion");
    level = (int) q1->level - 1;
    if (level >= 0) {
      index1 = p4est_quadrant_linear_id (q1, level);
      p4est_quadrant_set_morton (&r, level, index1);
      index2 = p4est_quadrant_linear_id (&r, level);
      SC_CHECK_ABORT (index1 == index2, "index conversion");
    }

    /* test the is_next function */
    if (p != NULL) {
      SC_CHECK_ABORT (p4est_quadrant_is_next (p, q1), "is_next");
    }
    p = q1;

    /* test the is_family function */
    p4est_quadrant_children (q1, &c0, &c1, &c2, &c3);
    SC_CHECK_ABORT (p4est_quadrant_is_family (&c0, &c1, &c2, &c3),
                    "is_family");
    SC_CHECK_ABORT (!p4est_quadrant_is_family (&c1, &c0, &c2, &c3),
                    "is_family");
    SC_CHECK_ABORT (!p4est_quadrant_is_family (&c0, &c0, &c1, &c2),
                    "is_family");
    p4est_quadrant_childrenv (q1, cv);
    SC_CHECK_ABORT (p4est_quadrant_is_equal (&c0, &cv[0]), "is_family");
    SC_CHECK_ABORT (p4est_quadrant_is_equal (&c1, &cv[1]), "is_family");
    SC_CHECK_ABORT (p4est_quadrant_is_equal (&c2, &cv[2]), "is_family");
    SC_CHECK_ABORT (p4est_quadrant_is_equal (&c3, &cv[3]), "is_family");
    SC_CHECK_ABORT (p4est_quadrant_is_family (&cv[0], &cv[1], &cv[2], &cv[3]),
                    "is_family");
    cp[0] = &cv[0];
    cp[1] = &cv[1];
    cp[2] = &cv[2];
    cp[3] = &cv[3];
    SC_CHECK_ABORT (p4est_quadrant_is_familypv (cp), "is_family");
    cv[1] = cv[0];
    SC_CHECK_ABORT (!p4est_quadrant_is_familyv (cv), "is_family");
    cp[1] = &c1;
    SC_CHECK_ABORT (p4est_quadrant_is_familypv (cp), "is_family");
    cp[2] = &c3;
    SC_CHECK_ABORT (!p4est_quadrant_is_familypv (cp), "is_family");

    /* test the sibling function */
    mid = p4est_quadrant_child_id (q1);
    for (cid = 0; cid < 4; ++cid) {
      p4est_quadrant_sibling (q1, &r, cid);
      if (cid != mid) {
        SC_CHECK_ABORT (p4est_quadrant_is_sibling (q1, &r), "sibling");
      }
      else {
        SC_CHECK_ABORT (p4est_quadrant_is_equal (q1, &r), "sibling");
      }
    }

    /* test t1 against itself */
    for (jz = 0; jz < t1->quadrants.elem_count; ++jz) {
      q2 = p4est_quadrant_array_index (&t1->quadrants, jz);

      /* test the comparison function */
      SC_CHECK_ABORT (p4est_quadrant_compare (q1, q2) ==
                      -p4est_quadrant_compare (q2, q1), "compare");
      SC_CHECK_ABORT ((p4est_quadrant_compare (q1, q2) == 0) ==
                      p4est_quadrant_is_equal (q1, q2), "is_equal");

      /* test the descriptive versions of functions */
      SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (q1, q2) ==
                      p4est_quadrant_is_sibling (q1, q2), "is_sibling");
      SC_CHECK_ABORT (p4est_quadrant_is_parent_D (q1, q2) ==
                      p4est_quadrant_is_parent (q1, q2), "is_parent");
      SC_CHECK_ABORT (p4est_quadrant_is_parent_D (q2, q1) ==
                      p4est_quadrant_is_parent (q2, q1), "is_parent");
      SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (q1, q2) ==
                      p4est_quadrant_is_ancestor (q1, q2), "is_ancestor");
      SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (q2, q1) ==
                      p4est_quadrant_is_ancestor (q2, q1), "is_ancestor");
      SC_CHECK_ABORT (p4est_quadrant_is_next_D (q1, q2) ==
                      p4est_quadrant_is_next (q1, q2), "is_next");
      SC_CHECK_ABORT (p4est_quadrant_is_next_D (q2, q1) ==
                      p4est_quadrant_is_next (q2, q1), "is_next");
      p4est_nearest_common_ancestor_D (q1, q2, &r);
      p4est_nearest_common_ancestor (q1, q2, &s);
      SC_CHECK_ABORT (p4est_quadrant_is_equal (&r, &s), "common_ancestor");
      p4est_nearest_common_ancestor_D (q2, q1, &r);
      p4est_nearest_common_ancestor (q2, q1, &s);
      SC_CHECK_ABORT (p4est_quadrant_is_equal (&r, &s), "common_ancestor");
    }

    /* test t1 against t2 */
    for (jz = 0; jz < t2->quadrants.elem_count; ++jz) {
      q2 = p4est_quadrant_array_index (&t2->quadrants, jz);

      /* test the comparison function */
      SC_CHECK_ABORT (p4est_quadrant_compare (q1, q2) ==
                      -p4est_quadrant_compare (q2, q1), "compare");
      SC_CHECK_ABORT ((p4est_quadrant_compare (q1, q2) == 0) ==
                      p4est_quadrant_is_equal (q1, q2), "is_equal");

      /* test the descriptive versions of functions */
      SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (q1, q2) ==
                      p4est_quadrant_is_sibling (q1, q2), "is_sibling");
      SC_CHECK_ABORT (p4est_quadrant_is_parent_D (q1, q2) ==
                      p4est_quadrant_is_parent (q1, q2), "is_parent");
      SC_CHECK_ABORT (p4est_quadrant_is_parent_D (q2, q1) ==
                      p4est_quadrant_is_parent (q2, q1), "is_parent");
      SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (q1, q2) ==
                      p4est_quadrant_is_ancestor (q1, q2), "is_ancestor");
      SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (q2, q1) ==
                      p4est_quadrant_is_ancestor (q2, q1), "is_ancestor");
      SC_CHECK_ABORT (p4est_quadrant_is_next_D (q1, q2) ==
                      p4est_quadrant_is_next (q1, q2), "is_next");
      SC_CHECK_ABORT (p4est_quadrant_is_next_D (q2, q1) ==
                      p4est_quadrant_is_next (q2, q1), "is_next");
      p4est_nearest_common_ancestor_D (q1, q2, &r);
      p4est_nearest_common_ancestor (q1, q2, &s);
      SC_CHECK_ABORT (p4est_quadrant_is_equal (&r, &s), "common_ancestor");
      p4est_nearest_common_ancestor_D (q2, q1, &r);
      p4est_nearest_common_ancestor (q2, q1, &s);
      SC_CHECK_ABORT (p4est_quadrant_is_equal (&r, &s), "common_ancestor");
    }
  }

  p = NULL;
  for (iz = 0; iz < t2->quadrants.elem_count; ++iz) {
    q1 = p4est_quadrant_array_index (&t2->quadrants, iz);

    /* test the is_next function */
    if (p != NULL) {
      SC_CHECK_ABORT (p4est_quadrant_is_next (p, q1), "is_next");
    }
    p = q1;
  }

  /* test the coarsen function */
  p4est_coarsen (p4est1, 1, coarsen_none, NULL);
  p4est_coarsen (p4est1, 1, coarsen_all, NULL);
  p4est_coarsen (p4est2, 1, coarsen_some, NULL);

  /* test the linearize algorithm */
  incount = t2->quadrants.elem_count;
  (void) p4est_linearize_tree (p4est2, t2);
  SC_CHECK_ABORT (incount == t2->quadrants.elem_count, "linearize");

  /* this is user_data neutral only when p4est1->data_size == 0 */
  sc_array_init (&tree.quadrants, sizeof (p4est_quadrant_t));
  sc_array_resize (&tree.quadrants, 18);
  q1 = p4est_quadrant_array_index (&tree.quadrants, 0);
  q2 = p4est_quadrant_array_index (&t2->quadrants, 0);
  *q1 = *q2;
  q2 = p4est_quadrant_array_index (&t2->quadrants, 1);
  for (k = 0; k < 3; ++k) {
    q1 = p4est_quadrant_array_index (&tree.quadrants, (size_t) (k + 1));
    *q1 = *q2;
    q1->level = (int8_t) (q1->level + k);
  }
  for (k = 0; k < 10; ++k) {
    q1 = p4est_quadrant_array_index (&tree.quadrants, (size_t) (k + 4));
    q2 = p4est_quadrant_array_index (&t2->quadrants, (size_t) (k + 3));
    *q1 = *q2;
    q1->level = (int8_t) (q1->level + k);
  }
  for (k = 0; k < 4; ++k) {
    q1 = p4est_quadrant_array_index (&tree.quadrants, (size_t) (k + 14));
    q2 = p4est_quadrant_array_index (&t2->quadrants, (size_t) (k + 12));
    *q1 = *q2;
    q1->level = (int8_t) (q1->level + 10 + k);
  }
  tree.maxlevel = 0;
  for (k = 0; k <= P4EST_QMAXLEVEL; ++k) {
    tree.quadrants_per_level[k] = 0;
  }
  for (; k <= P4EST_MAXLEVEL; ++k) {
    tree.quadrants_per_level[k] = -1;
  }
  incount = tree.quadrants.elem_count;
  for (iz = 0; iz < incount; ++iz) {
    q1 = p4est_quadrant_array_index (&tree.quadrants, iz);
    ++tree.quadrants_per_level[q1->level];
    tree.maxlevel = (int8_t) SC_MAX (tree.maxlevel, q1->level);
  }
  SC_CHECK_ABORT (!p4est_tree_is_linear (&tree), "is_linear");
  (void) p4est_linearize_tree (p4est1, &tree);
  SC_CHECK_ABORT (incount - 3 == tree.quadrants.elem_count, "linearize");
  sc_array_reset (&tree.quadrants);

  /* create a partial tree and check overlap */
  sc_array_resize (&tree.quadrants, 3);
  q1 = p4est_quadrant_array_index (&tree.quadrants, 0);
  p4est_quadrant_set_morton (q1, 1, 1);
  q1 = p4est_quadrant_array_index (&tree.quadrants, 1);
  p4est_quadrant_set_morton (q1, 2, 8);
  q1 = p4est_quadrant_array_index (&tree.quadrants, 2);
  p4est_quadrant_set_morton (q1, 2, 9);
  for (k = 0; k <= P4EST_QMAXLEVEL; ++k) {
    tree.quadrants_per_level[k] = 0;
  }
  for (; k <= P4EST_MAXLEVEL; ++k) {
    tree.quadrants_per_level[k] = -1;
  }
  tree.quadrants_per_level[1] = 1;
  tree.quadrants_per_level[2] = 2;
  tree.maxlevel = 2;
  p4est_quadrant_first_descendant (p4est_quadrant_array_index
                                   (&tree.quadrants, 0), &tree.first_desc,
                                   P4EST_QMAXLEVEL);
  p4est_quadrant_last_descendant (p4est_quadrant_array_index
                                  (&tree.quadrants,
                                   tree.quadrants.elem_count - 1),
                                  &tree.last_desc, P4EST_QMAXLEVEL);
  SC_CHECK_ABORT (p4est_tree_is_complete (&tree), "is_complete");

  p4est_quadrant_set_morton (&D, 0, 0);
  SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &D), "overlaps 0");

  p4est_quadrant_set_morton (&A, 1, 0);
  SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &A), "overlaps 1");
  p4est_quadrant_set_morton (&A, 1, 1);
  SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &A), "overlaps 2");
  p4est_quadrant_set_morton (&A, 1, 2);
  SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &A), "overlaps 3");
  p4est_quadrant_set_morton (&A, 1, 3);
  SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &A), "overlaps 4");

  p4est_quadrant_set_morton (&B, 3, 13);
  SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &B), "overlaps 5");
  p4est_quadrant_set_morton (&B, 3, 25);
  SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &B), "overlaps 6");
  p4est_quadrant_set_morton (&B, 3, 39);
  SC_CHECK_ABORT (p4est_quadrant_overlaps_tree (&tree, &B), "overlaps 7");
  p4est_quadrant_set_morton (&B, 3, 40);
  SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &B), "overlaps 8");

  p4est_quadrant_set_morton (&C, 4, 219);
  SC_CHECK_ABORT (!p4est_quadrant_overlaps_tree (&tree, &C), "overlaps 9");

  sc_array_reset (&tree.quadrants);

  /* destroy the p4est and its connectivity structure */
  p4est_destroy (p4est1);
  p4est_destroy (p4est2);
  p4est_connectivity_destroy (connectivity);

  /* This will test the ability to address negative quadrants */
  P4EST_QUADRANT_INIT (&A);
  P4EST_QUADRANT_INIT (&B);
  P4EST_QUADRANT_INIT (&C);
  P4EST_QUADRANT_INIT (&D);
  P4EST_QUADRANT_INIT (&E);
  P4EST_QUADRANT_INIT (&F);
  P4EST_QUADRANT_INIT (&G);
  P4EST_QUADRANT_INIT (&H);
  P4EST_QUADRANT_INIT (&I);
  P4EST_QUADRANT_INIT (&P);
  P4EST_QUADRANT_INIT (&Q);

  A.x = -qone << P4EST_MAXLEVEL;
  A.y = -qone << P4EST_MAXLEVEL;
  A.level = 0;

  B.x = qone << P4EST_MAXLEVEL;
  B.y = -qone << P4EST_MAXLEVEL;
  B.level = 0;

  C.x = -qone << P4EST_MAXLEVEL;
  C.y = qone << P4EST_MAXLEVEL;
  C.level = 0;

  D.x = qone << P4EST_MAXLEVEL;
  D.y = qone << P4EST_MAXLEVEL;
  D.level = 0;

  /* this one is outside the 3x3 box */
  E.x = -qone << (P4EST_MAXLEVEL + 1);
  E.y = -qone;
  E.level = 0;

  F.x = P4EST_ROOT_LEN + (P4EST_ROOT_LEN - mh);
  F.y = P4EST_ROOT_LEN + (P4EST_ROOT_LEN - mh);
  F.level = P4EST_QMAXLEVEL;

  G.x = -mh;
  G.y = -mh;
  G.level = P4EST_QMAXLEVEL;

  H.x = -qone << (P4EST_MAXLEVEL - 1);
  H.y = -qone << (P4EST_MAXLEVEL - 1);
  H.level = 1;

  I.x = -qone << P4EST_MAXLEVEL;
  I.y = -qone << (P4EST_MAXLEVEL - 1);
  I.level = 1;

  check_linear_id (&A, &A);
  check_linear_id (&A, &B);
  check_linear_id (&A, &C);
  check_linear_id (&A, &D);
  /* check_linear_id (&A, &E); */
  check_linear_id (&A, &F);
  check_linear_id (&A, &G);
  check_linear_id (&A, &H);
  check_linear_id (&A, &I);

  check_linear_id (&B, &A);
  check_linear_id (&B, &B);
  check_linear_id (&B, &C);
  check_linear_id (&B, &D);
  /* check_linear_id (&B, &E); */
  check_linear_id (&B, &F);
  check_linear_id (&B, &G);
  check_linear_id (&B, &H);
  check_linear_id (&B, &I);

  check_linear_id (&D, &A);
  check_linear_id (&D, &B);
  check_linear_id (&D, &C);
  check_linear_id (&D, &D);
  /* check_linear_id (&D, &E); */
  check_linear_id (&D, &F);
  check_linear_id (&D, &G);
  check_linear_id (&D, &H);
  check_linear_id (&D, &I);

  check_linear_id (&G, &A);
  check_linear_id (&G, &B);
  check_linear_id (&G, &C);
  check_linear_id (&G, &D);
  /* check_linear_id (&G, &E); */
  check_linear_id (&G, &F);
  check_linear_id (&G, &G);
  check_linear_id (&G, &H);
  check_linear_id (&G, &I);

  check_linear_id (&I, &A);
  check_linear_id (&I, &B);
  check_linear_id (&I, &C);
  check_linear_id (&I, &D);
  /* check_linear_id (&I, &E); */
  check_linear_id (&I, &F);
  check_linear_id (&I, &G);
  check_linear_id (&I, &H);
  check_linear_id (&I, &I);

  SC_CHECK_ABORT (p4est_quadrant_is_extended (&A) == 1, "is_extended A");
  SC_CHECK_ABORT (p4est_quadrant_is_extended (&B) == 1, "is_extended B");
  SC_CHECK_ABORT (p4est_quadrant_is_extended (&C) == 1, "is_extended C");
  SC_CHECK_ABORT (p4est_quadrant_is_extended (&D) == 1, "is_extended D");
  SC_CHECK_ABORT (!p4est_quadrant_is_extended (&E) == 1, "!is_extended E");
  SC_CHECK_ABORT (p4est_quadrant_is_extended (&F) == 1, "is_extended F");
  SC_CHECK_ABORT (p4est_quadrant_is_extended (&G) == 1, "is_extended G");

  SC_CHECK_ABORT (p4est_quadrant_compare (&A, &A) == 0, "compare");
  SC_CHECK_ABORT (p4est_quadrant_compare (&A, &B) > 0, "compare");
  SC_CHECK_ABORT (p4est_quadrant_compare (&B, &A) < 0, "compare");

  SC_CHECK_ABORT (p4est_quadrant_compare (&F, &F) == 0, "compare");
  SC_CHECK_ABORT (p4est_quadrant_compare (&G, &F) > 0, "compare");
  SC_CHECK_ABORT (p4est_quadrant_compare (&F, &G) < 0, "compare");

  A.p.which_tree = 0;
  B.p.piggy1.which_tree = 0;
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&A, &A) == 0,
                  "compare_piggy");
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&A, &B) > 0, "compare_piggy");
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&B, &A) < 0, "compare_piggy");

  F.p.piggy2.which_tree = 0;
  G.p.which_tree = 0;
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&F, &F) == 0,
                  "compare_piggy");
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&G, &F) > 0, "compare_piggy");
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&F, &G) < 0, "compare_piggy");

  F.p.piggy1.which_tree = (p4est_topidx_t) P4EST_TOPIDX_MAX - 3;
  G.p.piggy2.which_tree = (p4est_topidx_t) P4EST_TOPIDX_MAX / 2;
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&F, &F) == 0,
                  "compare_piggy");
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&G, &F) < 0, "compare_piggy");
  SC_CHECK_ABORT (p4est_quadrant_compare_piggy (&F, &G) > 0, "compare_piggy");

  SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &A) == 1, "is_equal");
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&F, &F) == 1, "is_equal");
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&G, &G) == 1, "is_equal");

  /* Not sure if these make sense because D, O and A are all level 0 */
#if 0
  SC_CHECK_ABORT (p4est_quadrant_is_sibling (&D, &O) == 1, "is_sibling");
  SC_CHECK_ABORT (p4est_quadrant_is_sibling (&D, &A) == 0, "is_sibling");
  SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (&D, &O) == 1, "is_sibling_D");
  SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (&D, &A) == 0, "is_sibling_D");
#endif

  SC_CHECK_ABORT (p4est_quadrant_is_sibling (&I, &H) == 1, "is_sibling");
  SC_CHECK_ABORT (p4est_quadrant_is_sibling (&I, &G) == 0, "is_sibling");
  SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (&I, &H) == 1, "is_sibling_D");
  SC_CHECK_ABORT (p4est_quadrant_is_sibling_D (&I, &G) == 0, "is_sibling_D");

  SC_CHECK_ABORT (p4est_quadrant_is_parent (&A, &H) == 1, "is_parent");
  SC_CHECK_ABORT (p4est_quadrant_is_parent (&H, &A) == 0, "is_parent");
  SC_CHECK_ABORT (p4est_quadrant_is_parent (&A, &D) == 0, "is_parent");
  SC_CHECK_ABORT (p4est_quadrant_is_parent_D (&A, &H) == 1, "is_parent_D");

  SC_CHECK_ABORT (p4est_quadrant_is_ancestor (&A, &G) == 1, "is_ancestor");
  SC_CHECK_ABORT (p4est_quadrant_is_ancestor (&G, &A) == 0, "is_ancestor");

  SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (&A, &G) == 1,
                  "is_ancestor_D");
  SC_CHECK_ABORT (p4est_quadrant_is_ancestor_D (&G, &A) == 0,
                  "is_ancestor_D");

  /* SC_CHECK_ABORT (p4est_quadrant_is_next (&F, &E) == 1, "is_next"); */
  SC_CHECK_ABORT (p4est_quadrant_is_next (&A, &H) == 0, "is_next");
  /* SC_CHECK_ABORT (p4est_quadrant_is_next_D (&F, &E) == 1, "is_next_D"); */
  SC_CHECK_ABORT (p4est_quadrant_is_next_D (&A, &H) == 0, "is_next_D");

  p4est_quadrant_parent (&H, &a);
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &a) == 1, "parent");

  p4est_quadrant_sibling (&I, &h, 3);
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&H, &h) == 1, "sibling");

  p4est_quadrant_children (&A, &c0, &c1, &c2, &c3);
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&c2, &I) == 1, "children");
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&c3, &H) == 1, "children");
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&c3, &G) == 0, "children");

  SC_CHECK_ABORT (p4est_quadrant_is_family (&c0, &c1, &c2, &c3) == 1,
                  "is_family");
  id0 = p4est_quadrant_child_id (&c0);
  id1 = p4est_quadrant_child_id (&c1);
  id2 = p4est_quadrant_child_id (&c2);
  id3 = p4est_quadrant_child_id (&c3);
  SC_CHECK_ABORT (id0 == 0 && id1 == 1 && id2 == 2 && id3 == 3, "child_id");
  SC_CHECK_ABORT (p4est_quadrant_child_id (&G) == 3, "child_id");

  p4est_quadrant_first_descendant (&A, &c1, 1);
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&c0, &c1) == 1,
                  "first_descendant");

  p4est_quadrant_last_descendant (&A, &g, P4EST_QMAXLEVEL);
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&G, &g) == 1, "last_descendant");

  Fid = p4est_quadrant_linear_id (&F, P4EST_QMAXLEVEL);
  p4est_quadrant_set_morton (&f, P4EST_QMAXLEVEL, Fid);
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&F, &f) == 1,
                  "set_morton/linear_id");

  Aid = p4est_quadrant_linear_id (&A, 0);
  p4est_quadrant_set_morton (&a, 0, Aid);
  SC_CHECK_ABORT (Aid == 15, "linear_id");
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &a) == 1,
                  "set_morton/linear_id");

  p4est_nearest_common_ancestor (&I, &H, &a);
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &a) == 1, "ancestor");

  p4est_nearest_common_ancestor_D (&I, &H, &a);
  SC_CHECK_ABORT (p4est_quadrant_is_equal (&A, &a) == 1, "ancestor_D");

  for (k = 0; k < 16; ++k) {
    if (k != 4 && k != 6 && k != 8 && k != 9 && k != 12 && k != 13 && k != 14) {
      p4est_quadrant_set_morton (&E, 0, (uint64_t) k);
    }
  }
  p4est_quadrant_set_morton (&P, 0, 10);
  p4est_quadrant_set_morton (&Q, 0, 11);
  SC_CHECK_ABORT (p4est_quadrant_is_next (&P, &Q), "is_next");
  SC_CHECK_ABORT (!p4est_quadrant_is_next (&A, &Q), "is_next");

  sc_finalize ();

  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
Пример #25
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;
}
Пример #26
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);
}
Пример #27
0
/** 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;
        }
      }
    }
  }
}
Пример #28
0
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;
}
Пример #29
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);
}
Пример #30
0
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;
}