Exemplo n.º 1
0
void
p4est_wrap_mark_coarsen (p4est_wrap_t * pp,
                         p4est_topidx_t which_tree, p4est_locidx_t which_quad)
{
  p4est_t            *p4est = pp->p4est;
  p4est_tree_t       *tree;
  p4est_locidx_t      pos;
  uint8_t             flag;

  P4EST_ASSERT (!pp->hollow);
  P4EST_ASSERT (p4est->first_local_tree <= which_tree);
  P4EST_ASSERT (which_tree <= p4est->last_local_tree);

  tree = p4est_tree_array_index (p4est->trees, which_tree);
  P4EST_ASSERT (0 <= which_quad &&
                which_quad < (p4est_locidx_t) tree->quadrants.elem_count);
  pos = tree->quadrants_offset + which_quad;
  P4EST_ASSERT (0 <= pos && pos < p4est->local_num_quadrants);

  flag = pp->flags[pos];
  if (flag & P4EST_WRAP_REFINE) {
    pp->flags[pos] &= ~P4EST_WRAP_REFINE;
    --pp->num_refine_flags;
  }
  pp->flags[pos] |= P4EST_WRAP_COARSEN;
}
Exemplo n.º 2
0
void
p4est_mesh_face_neighbor_init (p4est_mesh_face_neighbor_t * mfn,
                               p4est_t * p4est, p4est_ghost_t * ghost,
                               p4est_mesh_t * mesh, p4est_topidx_t which_tree,
                               p4est_quadrant_t * quadrant)
{
  p4est_locidx_t      quadrant_id;
  p4est_tree_t       *tree;

  mfn->p4est = p4est;
  mfn->ghost = ghost;
  mfn->mesh = mesh;

  P4EST_ASSERT (0 <= which_tree &&
                which_tree < p4est->connectivity->num_trees);
  mfn->which_tree = which_tree;
  tree = p4est_tree_array_index (p4est->trees, which_tree);

  quadrant_id =
    (p4est_locidx_t) sc_array_position (&tree->quadrants, quadrant);
  mfn->quadrant_id = quadrant_id;
  mfn->quadrant_code = P4EST_FACES * (tree->quadrants_offset + quadrant_id);

  mfn->face = 0;
  mfn->subface = 0;
  mfn->current_qtq = -1;
}
Exemplo n.º 3
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;
    }
  }
}
Exemplo n.º 4
0
void
p4est_wrap_set_coarsen_delay (p4est_wrap_t * pp,
                              int coarsen_delay, int coarsen_affect)
{
  size_t              zz;
  p4est_topidx_t      tt;
  p4est_t            *p4est;
  p4est_tree_t       *tree;
  p4est_quadrant_t   *quadrant;
  sc_array_t         *tquadrants;

  P4EST_ASSERT (pp != NULL);
  P4EST_ASSERT (coarsen_delay >= 0);

  pp->coarsen_delay = coarsen_delay;
  pp->coarsen_affect = coarsen_affect;
  p4est = pp->p4est;
  P4EST_ASSERT (p4est->data_size == 0);

  /* initialize delay memory in the quadrants' user field */
  for (tt = p4est->first_local_tree; tt <= p4est->last_local_tree; ++tt) {
    tree = p4est_tree_array_index (p4est->trees, tt);
    tquadrants = &tree->quadrants;
    for (zz = 0; zz < tquadrants->elem_count; ++zz) {
      quadrant = p4est_quadrant_array_index (tquadrants, zz);
      quadrant->p.user_int = 0;
    }
  }
}
Exemplo n.º 5
0
p4est_wrap_leaf_t  *
p4est_wrap_leaf_next (p4est_wrap_leaf_t * leaf)
{
  p4est_t            *p4est = leaf->pp->p4est;

  P4EST_ASSERT (leaf != NULL);

  if ((size_t) leaf->which_quad + 1 == leaf->tquadrants->elem_count) {
    ++leaf->which_tree;
    if (leaf->which_tree > p4est->last_local_tree) {
#ifdef P4EST_ENABLE_DEBUG
      if (leaf->mirrors != NULL) {
        P4EST_ASSERT (leaf->nm + 1 ==
                      (p4est_locidx_t) leaf->mirrors->elem_count);
        P4EST_ASSERT (leaf->next_mirror_quadrant == -1);
      }
#endif
      P4EST_FREE (leaf);
      return NULL;
    }
    leaf->tree = p4est_tree_array_index (p4est->trees, leaf->which_tree);
    leaf->tquadrants = &leaf->tree->quadrants;
    P4EST_ASSERT (leaf->tquadrants->elem_size > 0);
    leaf->which_quad = 0;
  }
  else {
    ++leaf->which_quad;
  }

  return p4est_wrap_leaf_info (leaf);
}
Exemplo n.º 6
0
p4est_quadrant_t   *
p4est_mesh_quadrant_cumulative (p4est_t * p4est, p4est_locidx_t cumulative_id,
                                p4est_topidx_t * which_tree,
                                p4est_locidx_t * quadrant_id)
{
  int                 the_quadrant_id;
  p4est_topidx_t      low_tree, high_tree, guess_tree;
  p4est_tree_t       *tree;

  P4EST_ASSERT (0 <= cumulative_id &&
                cumulative_id < p4est->local_num_quadrants);

  low_tree = p4est->first_local_tree;
  high_tree = p4est->last_local_tree;
  if (which_tree != NULL && *which_tree != -1) {
    guess_tree = *which_tree;
  }
  else {
    guess_tree = (low_tree + high_tree) / 2;
  }
  for (;;) {
    P4EST_ASSERT (p4est->first_local_tree <= low_tree);
    P4EST_ASSERT (high_tree <= p4est->last_local_tree);
    P4EST_ASSERT (low_tree <= guess_tree && guess_tree <= high_tree);

    tree = p4est_tree_array_index (p4est->trees, guess_tree);
    if (cumulative_id < tree->quadrants_offset) {
      high_tree = guess_tree - 1;
    }
    else if (cumulative_id >= tree->quadrants_offset +
             (p4est_locidx_t) tree->quadrants.elem_count) {
      low_tree = guess_tree + 1;
    }
    else {
      the_quadrant_id = cumulative_id - tree->quadrants_offset;
      P4EST_ASSERT (0 <= the_quadrant_id);

      if (which_tree != NULL) {
        *which_tree = guess_tree;
      }
      if (quadrant_id != NULL) {
        *quadrant_id = the_quadrant_id;
      }
      return p4est_quadrant_array_index (&tree->quadrants,
                                         (size_t) the_quadrant_id);
    }
    guess_tree = (low_tree + high_tree) / 2;
  }
}
Exemplo n.º 7
0
p4est_wrap_leaf_t  *
p4est_wrap_leaf_first (p4est_wrap_t * pp, int track_mirrors)
{
  p4est_t            *p4est = pp->p4est;
  p4est_wrap_leaf_t  *leaf;
  p4est_quadrant_t   *mirror;

  if (p4est->local_num_quadrants == 0) {
    P4EST_ASSERT (p4est->first_local_tree == -1);
    P4EST_ASSERT (p4est->last_local_tree == -2);
    return NULL;
  }

  /* prepare internal state of the leaf iterator */
  leaf = P4EST_ALLOC (p4est_wrap_leaf_t, 1);
  leaf->pp = pp;
  leaf->which_tree = p4est->first_local_tree;
  P4EST_ASSERT (leaf->which_tree >= 0);
  leaf->tree = p4est_tree_array_index (p4est->trees, leaf->which_tree);
  leaf->tquadrants = &leaf->tree->quadrants;
  P4EST_ASSERT (leaf->tquadrants->elem_size > 0);
  leaf->which_quad = 0;

  /* initialize mirror tracking if desired */
  leaf->nm = leaf->next_mirror_quadrant = -1;
  if (track_mirrors) {
    leaf->mirrors = &(p4est_wrap_get_ghost (pp))->mirrors;
    if (leaf->mirrors->elem_count > 0) {
      mirror = p4est_quadrant_array_index (leaf->mirrors, 0);
      leaf->next_mirror_quadrant = (int) mirror->p.piggy3.local_num;
      P4EST_ASSERT (leaf->next_mirror_quadrant >= 0);
      P4EST_ASSERT (leaf->next_mirror_quadrant < p4est->local_num_quadrants);
    }
  }
  else {
    leaf->mirrors = NULL;
    leaf->is_mirror = 0;
  }

  /* complete leaf and mirror information */
  return p4est_wrap_leaf_info (leaf);
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
static void
mesh_iter_volume (p4est_iter_volume_info_t * info, void *user_data)
{
  p4est_mesh_t       *mesh = (p4est_mesh_t *) user_data;
  p4est_tree_t       *tree;
  p4est_locidx_t     *quadid;
  int                 level = info->quad->level;

  /* We could use a static quadrant counter, but that gets uglier */
  tree = p4est_tree_array_index (info->p4est->trees, info->treeid);
  P4EST_ASSERT (0 <= info->quadid &&
                info->quadid < (p4est_locidx_t) tree->quadrants.elem_count);

  if (mesh->quad_to_tree != NULL) {
    mesh->quad_to_tree[tree->quadrants_offset + info->quadid] = info->treeid;
  }

  if (mesh->quad_level != NULL) {
    quadid = (p4est_locidx_t *) sc_array_push (mesh->quad_level + level);
    *quadid = tree->quadrants_offset + info->quadid;
  }
}
Exemplo n.º 10
0
static void
p4est_build_verify_4 (p4est_t * p4est)
{
  p4est_topidx_t      jt;
  p4est_locidx_t      il, c1, c2;
  p4est_tree_t       *tree;
  p4est_quadrant_t   *quadrant;
  test_build_t       *tb;

  tb = (test_build_t *) p4est->user_pointer;

  c1 = c2 = 0;
  for (jt = p4est->first_local_tree; jt <= p4est->last_local_tree; ++jt) {
    tree = p4est_tree_array_index (p4est->trees, jt);
    for (il = 0; il < (p4est_locidx_t) tree->quadrants.elem_count; ++il) {
      quadrant = p4est_quadrant_array_index (&tree->quadrants, il);
      switch (*(long *) quadrant->p.user_data) {
      case 11321:
        ++c1;
        break;
      case -748:
        ++c2;
        break;
      default:
        SC_ABORT_NOT_REACHED ();
      }
    }
  }
  SC_CHECK_ABORT (c1 + c2 == p4est->local_num_quadrants,
                  "Test 4 count quadrants");
  SC_CHECK_ABORT (c1 + c2 >= (p4est_locidx_t) tb->count_add,
                  "Test 4 count sum");
  SC_CHECK_ABORT (c1 == (p4est_locidx_t) tb->init_default,
                  "Test 4 count default");
  SC_CHECK_ABORT (c2 == (p4est_locidx_t) tb->init_add, "Test 4 count add");
}
Exemplo n.º 11
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;
  }

}
Exemplo n.º 12
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);
}
Exemplo n.º 13
0
int
main (int argc, char **argv)
{
  sc_MPI_Comm         mpicomm;
  int                 mpiret;
  int                 found_total;
  p4est_locidx_t      jt, Al, Bl;
  p4est_locidx_t      local_count;
  p4est_connectivity_t *conn;
  p4est_quadrant_t   *A, *B;
  p4est_geometry_t   *geom;
  p4est_t            *p4est;
  sc_array_t         *points;
  test_point_t       *p;
  const char         *vtkname;

  /* Initialize MPI */
  mpiret = sc_MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);
  mpicomm = sc_MPI_COMM_WORLD;

  /* Initialize packages */
  sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT);
  p4est_init (NULL, SC_LP_DEFAULT);

  /* Create forest */
#ifndef P4_TO_P8
  conn = p4est_connectivity_new_star ();
  geom = NULL;
  vtkname = "test_search2";
#else
  conn = p8est_connectivity_new_sphere ();
  geom = p8est_geometry_new_sphere (conn, 1., 0.191728, 0.039856);
  vtkname = "test_search3";
#endif
  p4est = p4est_new_ext (mpicomm, conn, 0, 0, 0, 0, NULL, &local_count);
  p4est_refine (p4est, 1, refine_fn, NULL);
  p4est_partition (p4est, 0, NULL);
  p4est_vtk_write_file (p4est, geom, vtkname);

  /* The following code should really be in a separate function. */

  /* Prepare a point search -- fix size so the memory is not relocated */
  points = sc_array_new_size (sizeof (test_point_t), 2);

  /* A */
  p = (test_point_t *) sc_array_index (points, 0);
  p->name = "A";
  A = &p->quad;
  P4EST_QUADRANT_INIT (A);
  p4est_quadrant_set_morton (A, 3, 23);
  A->p.piggy3.which_tree = 0;
  A->p.piggy3.local_num = -1;
  Al = -1;

  /* B */
  p = (test_point_t *) sc_array_index (points, 1);
  p->name = "B";
  B = &p->quad;
  P4EST_QUADRANT_INIT (B);
  p4est_quadrant_set_morton (B, 2, 13);
  B->p.piggy3.which_tree = conn->num_trees / 2;
  B->p.piggy3.local_num = -1;
  Bl = -1;

  /* Find quadrant numbers if existing */
  for (jt = p4est->first_local_tree; jt <= p4est->last_local_tree; ++jt) {
    size_t              zz;
    p4est_tree_t       *tree = p4est_tree_array_index (p4est->trees, jt);
    p4est_quadrant_t   *quad;
    sc_array_t         *tquadrants = &tree->quadrants;

    for (zz = 0; zz < tquadrants->elem_count; ++zz) {
      quad = p4est_quadrant_array_index (tquadrants, zz);
      if (A->p.piggy3.which_tree == jt && !p4est_quadrant_compare (quad, A)) {
        Al = tree->quadrants_offset + (p4est_locidx_t) zz;
        P4EST_VERBOSEF ("Searching for A at %lld\n", (long long) Al);
      }
      if (B->p.piggy3.which_tree == jt && !p4est_quadrant_compare (quad, B)) {
        Bl = tree->quadrants_offset + (p4est_locidx_t) zz;
        P4EST_VERBOSEF ("Searching for B at %lld\n", (long long) Bl);
      }
    }
  }

  /* Go */
  found_count = 0;
  p4est_search_local (p4est, 0, NULL, search_callback, points);
  mpiret = sc_MPI_Allreduce (&found_count, &found_total,
                             1, sc_MPI_INT, sc_MPI_SUM, mpicomm);
  SC_CHECK_MPI (mpiret);
  SC_CHECK_ABORT (found_total == (int) points->elem_count, "Point search");
  SC_CHECK_ABORT (A->p.piggy3.local_num == Al, "Search A");
  SC_CHECK_ABORT (B->p.piggy3.local_num == Bl, "Search B");

  /* Use another search to count local quadrants */
  local_count = 0;
  p4est_search_local (p4est, 0, count_callback, NULL, NULL);
  SC_CHECK_ABORT (local_count == p4est->local_num_quadrants, "Count search");

  /* Clear memory */
  sc_array_destroy (points);
  p4est_destroy (p4est);
  if (geom != NULL) {
    p4est_geometry_destroy (geom);
  }
  p4est_connectivity_destroy (conn);

  /* Test the build_local function and friends */
  test_build_local (mpicomm);

  /* Finalize */
  sc_finalize ();
  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
Exemplo n.º 14
0
Arquivo: mesh2.c Projeto: holke/p4est
static void
test_mesh (p4est_t * p4est, p4est_ghost_t * ghost, p4est_mesh_t * mesh,
           int compute_tree_index, int compute_level_lists,
           p4est_connect_type_t mesh_btype,
           user_data_t * ghost_data, int uniform)
{
  const int           HF = P4EST_HALF * P4EST_FACES;
  size_t              i;
  int                 level;
  int                 f, nf;
  int                 c;
  int                 nface;
  int                 nrank;
  p4est_topidx_t      which_tree;
  p4est_locidx_t      K, kl;
  p4est_locidx_t      ql, QpG, lnC;
  p4est_locidx_t      qlid, qumid, quadrant_id, which_quad;
  p4est_mesh_face_neighbor_t mfn, mfn2;
  p4est_quadrant_t   *q;
  p4est_tree_t       *tree;

  K = mesh->local_num_quadrants;
  P4EST_ASSERT (K == p4est->local_num_quadrants);
  QpG = mesh->local_num_quadrants + mesh->ghost_num_quadrants;
  lnC = mesh->local_num_corners;
  P4EST_ASSERT (lnC >= 0);

  P4EST_ASSERT (compute_tree_index == (mesh->quad_to_tree != NULL));
  P4EST_ASSERT (compute_level_lists == (mesh->quad_level != NULL));
  P4EST_ASSERT ((mesh_btype == P4EST_CONNECT_CORNER) ==
                (mesh->quad_to_corner != NULL));

  /* TODO: test the mesh relations in more depth */
  tree = NULL;
  for (kl = 0; kl < K; ++kl) {
    if (compute_tree_index) {
      tree = p4est_tree_array_index (p4est->trees, mesh->quad_to_tree[kl]);
      SC_CHECK_ABORTF (tree->quadrants_offset <= kl && kl <
                       tree->quadrants_offset +
                       (p4est_locidx_t) tree->quadrants.elem_count,
                       "Tree index mismatch %lld", (long long) kl);
    }

    if (mesh_btype == P4EST_CONNECT_CORNER) {
      for (c = 0; c < P4EST_CHILDREN; ++c) {
        qlid = mesh->quad_to_corner[P4EST_CHILDREN * kl + c];
        SC_CHECK_ABORTF (qlid >= -2
                         && qlid < QpG + lnC, "quad %lld corner %d mismatch",
                         (long long) kl, c);
      }
    }
    for (f = 0; f < P4EST_FACES; ++f) {
      ql = mesh->quad_to_quad[P4EST_FACES * kl + f];
      SC_CHECK_ABORTF (0 <= ql && ql < QpG,
                       "quad %d face %d neighbor %d mismatch", kl, f, ql);
      nf = mesh->quad_to_face[P4EST_FACES * kl + f];
      if (uniform) {
        SC_CHECK_ABORTF (0 <= nf && nf < HF,
                         "quad %d face %d code %d mismatch", kl, f, nf);
      }
      else {
        SC_CHECK_ABORTF (-HF <= nf && nf < (P4EST_HALF + 1) * HF,
                         "quad %d face %d code %d mismatch", kl, f, nf);
      }
    }
  }

  /* Test the level lists */
  if (compute_tree_index && compute_level_lists) {
    for (level = 0; level < P4EST_QMAXLEVEL; ++level) {
      for (i = 0; i < mesh->quad_level[level].elem_count; ++i) {
        /* get the local quadrant id */
        quadrant_id =
          *(p4est_locidx_t *) sc_array_index (&mesh->quad_level[level], i);

        /* get the tree it belongs to */
        kl = mesh->quad_to_tree[quadrant_id];
        tree = p4est_tree_array_index (p4est->trees, kl);

        /* and finally, get the actual quadrant from the tree quadrant list */
        quadrant_id -= tree->quadrants_offset;
        q =
          p4est_quadrant_array_index (&tree->quadrants, (size_t) quadrant_id);

        SC_CHECK_ABORTF (q->level == level,
                         "quad %d level %d mismatch", quadrant_id, level);
      }
    }
  }

  /* Test face neighbor iterator */
  for (qumid = 0; qumid < mesh->local_num_quadrants; ++qumid) {
    which_tree = -1;
    q = p4est_mesh_quadrant_cumulative (p4est, qumid,
                                        &which_tree, &quadrant_id);
    p4est_mesh_face_neighbor_init2 (&mfn, p4est, ghost, mesh,
                                    which_tree, quadrant_id);
    p4est_mesh_face_neighbor_init (&mfn2, p4est, ghost, mesh, which_tree, q);
    P4EST_ASSERT (mfn2.quadrant_id == quadrant_id);
    while ((q = p4est_mesh_face_neighbor_next (&mfn, &which_tree, &which_quad,
                                               &nface, &nrank)) != NULL) {
#ifdef P4EST_ENABLE_DEBUG
      user_data_t        *data;

      data = (user_data_t *) p4est_mesh_face_neighbor_data (&mfn, ghost_data);

      P4EST_ASSERT (p4est_quadrant_is_equal (q, &(data->quad)));
      P4EST_ASSERT (data->quad.p.which_tree == which_tree);
#endif
    }
  }
}
Exemplo n.º 15
0
p6est_profile_t    *
p6est_profile_new_local (p6est_t * p6est,
                         p6est_ghost_t * ghost,
                         p6est_profile_type_t ptype,
                         p8est_connect_type_t btype, int degree)
{
  p6est_profile_t    *profile = P4EST_ALLOC (p6est_profile_t, 1);
  p4est_lnodes_t     *lnodes;
  p4est_locidx_t      nln, nle;
  p4est_topidx_t      jt;
  p4est_t            *columns = p6est->columns;
  p4est_tree_t       *tree;
  sc_array_t         *tquadrants;
  p4est_quadrant_t   *col;
  p4est_qcoord_t      diff = P4EST_ROOT_LEN - p6est->root_len;
  size_t              first, last, count, zz, zy;
  p4est_locidx_t     *en, (*lr)[2];
  sc_array_t         *lc;
  int                 i, j;
  p2est_quadrant_t   *layer;
  sc_array_t         *layers = p6est->layers;
  p4est_locidx_t      nidx, enidx;
  p4est_connect_type_t hbtype;
  int8_t             *c;
  sc_array_t         *thisprof;
  sc_array_t         *selfprof;
  sc_array_t         *faceprof;
  sc_array_t         *cornerprof;
  sc_array_t         *work;
  sc_array_t          oldprof;
  const int           Nrp = degree + 1;

  P4EST_ASSERT (degree > 1);
  profile->ptype = ptype;
  profile->btype = btype;
  profile->lnode_changed[0] = NULL;
  profile->lnode_changed[1] = NULL;
  profile->enode_counts = NULL;
  profile->diff = diff;
  if (btype == P8EST_CONNECT_FACE) {
    hbtype = P4EST_CONNECT_FACE;
  }
  else {
    hbtype = P4EST_CONNECT_FULL;
  }
  if (ghost == NULL) {
    profile->cghost = p4est_ghost_new (p6est->columns, P4EST_CONNECT_FULL);
    profile->ghost_owned = 1;
  }
  else {
    P4EST_ASSERT (ghost->column_ghost->btype == P4EST_CONNECT_FULL);
    profile->cghost = ghost->column_ghost;
    profile->ghost_owned = 0;
  }
  if (ptype == P6EST_PROFILE_UNION) {
    P4EST_ASSERT (degree == 2);
  }
  profile->lnodes = lnodes = p4est_lnodes_new (p6est->columns,
                                               profile->cghost, degree);
  en = lnodes->element_nodes;
  nln = lnodes->num_local_nodes;
  nle = lnodes->num_local_elements;
  profile->lnode_ranges = P4EST_ALLOC_ZERO (p4est_locidx_t, 2 * nln);
  lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges;
  profile->lnode_columns = lc = sc_array_new (sizeof (int8_t));
  selfprof = sc_array_new (sizeof (int8_t));
  work = sc_array_new (sizeof (int8_t));
  faceprof = sc_array_new (sizeof (int8_t));
  cornerprof = sc_array_new (sizeof (int8_t));
  if (ptype == P6EST_PROFILE_UNION) {
    profile->lnode_changed[0] = P4EST_ALLOC (p4est_locidx_t, nln);
    profile->lnode_changed[1] = P4EST_ALLOC (p4est_locidx_t, nln);
    profile->enode_counts = P4EST_ALLOC (p4est_locidx_t, P4EST_INSUL * nle);
    profile->evenodd = 0;
    memset (profile->lnode_changed[0], -1, nln * sizeof (int));
  }

  /* create the profiles for each node: layers are reduced to just their level
   * */
  for (enidx = 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) {
      col = p4est_quadrant_array_index (tquadrants, zz);
      P6EST_COLUMN_GET_RANGE (col, &first, &last);
      count = last - first;
      sc_array_truncate (selfprof);
      c = (int8_t *) sc_array_push_count (selfprof, count);
      for (zy = first; zy < last; zy++) {
        layer = p2est_quadrant_array_index (layers, zy);
        *(c++) = layer->level;
      }
      if (ptype == P6EST_PROFILE_UNION) {
        p6est_profile_balance_self (selfprof, work);
        if (btype == P8EST_CONNECT_FACE) {
          p6est_profile_balance_face (selfprof, faceprof, work, diff);
        }
        else {
          p6est_profile_balance_full (selfprof, faceprof, work, diff);
        }
        if (btype == P8EST_CONNECT_EDGE) {
          p6est_profile_balance_face (selfprof, cornerprof, work, diff);
        }
        else if (btype == P8EST_CONNECT_FULL) {
          p6est_profile_balance_full (selfprof, cornerprof, work, diff);
        }
      }
      for (j = 0; j < Nrp; j++) {
        for (i = 0; i < Nrp; i++, enidx++) {
          nidx = en[enidx];
          if (ptype == P6EST_PROFILE_UNION) {
            thisprof = NULL;
            if (!(i % degree) && !(j % degree)) {
              if (hbtype == P4EST_CONNECT_FACE) {
                /* skip corners if we don't need to balance them */
                P4EST_ASSERT (!lr[nidx][0]);
                P4EST_ASSERT (!lr[nidx][1]);
                continue;
              }
              else {
                thisprof = cornerprof;
              }
            }
            else if ((i % degree) && (j % degree)) {
              thisprof = selfprof;
            }
            else {
              thisprof = faceprof;
            }
            count = thisprof->elem_count;
            profile->enode_counts[enidx] = count;
            if (!lr[nidx][1]) {
              /* if this node has not yet been initialized, initialize it */
              lr[nidx][0] = lc->elem_count;
              lr[nidx][1] = count;
              c = (int8_t *) sc_array_push_count (lc, count);
              memcpy (c, thisprof->array, count * sizeof (int8_t));
            }
            else {
              /* if this node has been initialized, combine the two profiles,
               * taking the finer layers from each */
              sc_array_init_view (&oldprof, lc, lr[nidx][0], lr[nidx][1]);
              p6est_profile_union (thisprof, &oldprof, work);
              if (work->elem_count > oldprof.elem_count) {
                lr[nidx][0] = lc->elem_count;
                lr[nidx][1] = work->elem_count;
                c = (int8_t *) sc_array_push_count (lc, work->elem_count);
                memcpy (c, work->array, work->elem_count * work->elem_size);
              }
            }
          }
          else {
            count = selfprof->elem_count;
            if (!lr[nidx][1]) {
              /* if this node has not yet been initialized, initialize it */
              lr[nidx][0] = lc->elem_count;
              lr[nidx][1] = count;
              c = (int8_t *) sc_array_push_count (lc, count);
              memcpy (c, selfprof->array, count * sizeof (int8_t));
            }
            else {
              /* if this node has been initialized, combine the two profiles,
               * taking the coarser layers from each */
              sc_array_init_view (&oldprof, lc, lr[nidx][0], lr[nidx][1]);
              p6est_profile_intersection (selfprof, &oldprof, work);
              P4EST_ASSERT (work->elem_count <= oldprof.elem_count);
              if (work->elem_count < oldprof.elem_count) {
                lr[nidx][1] = work->elem_count;
                memcpy (oldprof.array, work->array,
                        work->elem_count * work->elem_size);
              }
            }
          }
        }
      }
    }
  }
  p6est_profile_compress (profile);

  sc_array_destroy (selfprof);
  sc_array_destroy (faceprof);
  sc_array_destroy (cornerprof);
  sc_array_destroy (work);

  return profile;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
int
main (int argc, char **argv)
{
  sc_MPI_Comm         mpicomm;
  int                 mpiret;
  int                 mpisize, mpirank;
  p4est_t            *p4est;
  p4est_connectivity_t *connectivity;
  sc_dmatrix_t       *vtkvec;
  p4est_tree_t       *tree;
  sc_array_t         *quadrants;
  size_t              zz, count;
  p4est_quadrant_t   *q;
  int                 i;
#ifndef P4_TO_P8
  char                filename[] = "p4est_balance_face";
#else
  char                filename[] = "p8est_balance_edge";
#endif
  p4est_vtk_context_t *context;
  sc_array_t         *level;
  int                 retval;

  /* initialize MPI */
  mpiret = sc_MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);
  mpicomm = sc_MPI_COMM_WORLD;
  mpiret = sc_MPI_Comm_size (mpicomm, &mpisize);
  SC_CHECK_MPI (mpiret);
  mpiret = sc_MPI_Comm_rank (mpicomm, &mpirank);
  SC_CHECK_MPI (mpiret);

  sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT);
  p4est_init (NULL, SC_LP_DEFAULT);

#ifndef P4_TO_P8
  connectivity = p4est_connectivity_new_unitsquare ();
#else
  connectivity = p8est_connectivity_new_unitcube ();
#endif

  p4est = p4est_new_ext (mpicomm, connectivity, 0, 2, 1,
                         sizeof (balance_seeds_elem_t), init_fn, NULL);

  p4est_refine (p4est, 1, refine_fn, init_fn);

  context = p4est_vtk_context_new (p4est, filename);
  p4est_vtk_context_set_scale (context, 1. - 2. * SC_EPS);
  context = p4est_vtk_write_header (context);
  SC_CHECK_ABORT (context != NULL, P4EST_STRING "_vtk: Error writing header");

  vtkvec = sc_dmatrix_new (p4est->local_num_quadrants, P4EST_CHILDREN);
  tree = p4est_tree_array_index (p4est->trees, 0);
  quadrants = &(tree->quadrants);
  count = quadrants->elem_count;
  for (zz = 0; zz < count; zz++) {
    q = p4est_quadrant_array_index (quadrants, zz);
    for (i = 0; i < P4EST_CHILDREN; i++) {
      vtkvec->e[zz][i] = (double)
        ((balance_seeds_elem_t *) (q->p.user_data))->flag;
    }
  }
  level =
    sc_array_new_data ((void *) vtkvec->e[0], sizeof (double),
                       count * P4EST_CHILDREN);
  context =
    p4est_vtk_write_point_dataf (context, 1, 0, "level", level, context);
  SC_CHECK_ABORT (context != NULL,
                  P4EST_STRING "_vtk: Error writing point data");
  sc_array_destroy (level);

  retval = p4est_vtk_write_footer (context);
  SC_CHECK_ABORT (!retval, P4EST_STRING "_vtk: Error writing footer");

  sc_dmatrix_destroy (vtkvec);
  p4est_destroy (p4est);
  p4est_connectivity_destroy (connectivity);

  sc_finalize ();

  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
Exemplo n.º 18
0
static void
mesh_iter_face (p4est_iter_face_info_t * info, void *user_data)
{
  int                 h;
  int                 swapsides;
  p4est_mesh_t       *mesh = (p4est_mesh_t *) user_data;
  p4est_locidx_t      jl, jl2, jls[P4EST_HALF];
  p4est_locidx_t      in_qtoq, halfindex;
  p4est_locidx_t     *halfentries;
  p4est_tree_t       *tree;
  p4est_iter_face_side_t *side, *side2, *tempside;

  if (info->sides.elem_count == 1) {
    /* this face is on an outside boundary of the forest */
    P4EST_ASSERT (info->orientation == 0);
    P4EST_ASSERT (info->tree_boundary);
    side = (p4est_iter_face_side_t *) sc_array_index (&info->sides, 0);
    P4EST_ASSERT (0 <= side->treeid &&
                  side->treeid < info->p4est->connectivity->num_trees);
    P4EST_ASSERT (0 <= side->face && side->face < P4EST_FACES);
    P4EST_ASSERT (!side->is_hanging && !side->is.full.is_ghost);
    tree = p4est_tree_array_index (info->p4est->trees, side->treeid);
    jl = side->is.full.quadid + tree->quadrants_offset;
    P4EST_ASSERT (0 <= jl && jl < mesh->local_num_quadrants);
    in_qtoq = P4EST_FACES * jl + side->face;
    mesh->quad_to_quad[in_qtoq] = jl;   /* put in myself and my own face */
    mesh->quad_to_face[in_qtoq] = side->face;
  }
  else {
    /* this face is between two quadrants */
    P4EST_ASSERT (info->orientation == 0 || info->tree_boundary);
    P4EST_ASSERT (info->sides.elem_count == 2);
    side = (p4est_iter_face_side_t *) sc_array_index (&info->sides, 0);
    side2 = (p4est_iter_face_side_t *) sc_array_index (&info->sides, 1);
    P4EST_ASSERT (info->tree_boundary || side->treeid == side2->treeid);
    P4EST_ASSERT (!side->is_hanging || !side2->is_hanging);
    if (!side->is_hanging && !side2->is_hanging) {
      /* same-size face neighbors */
      P4EST_ASSERT (!side->is.full.is_ghost || !side2->is.full.is_ghost);

      /* determine both quadrant numbers */
      if (!side->is.full.is_ghost) {
        tree = p4est_tree_array_index (info->p4est->trees, side->treeid);
        jl = side->is.full.quadid + tree->quadrants_offset;
        P4EST_ASSERT (0 <= jl && jl < mesh->local_num_quadrants);
      }
      else {
        P4EST_ASSERT (side->is.full.quad != NULL);
        P4EST_ASSERT (side->is.full.quadid >= 0);
        jl = mesh->local_num_quadrants + side->is.full.quadid;
      }
      if (!side2->is.full.is_ghost) {
        tree = p4est_tree_array_index (info->p4est->trees, side2->treeid);
        jl2 = side2->is.full.quadid + tree->quadrants_offset;
        P4EST_ASSERT (0 <= jl2 && jl2 < mesh->local_num_quadrants);
      }
      else {
        P4EST_ASSERT (side2->is.full.quad != NULL);
        P4EST_ASSERT (side2->is.full.quadid >= 0);
        jl2 = mesh->local_num_quadrants + side2->is.full.quadid;
      }

      /* encode quadrant neighborhood */
      if (!side->is.full.is_ghost) {
        in_qtoq = P4EST_FACES * jl + side->face;
        P4EST_ASSERT (mesh->quad_to_quad[in_qtoq] == -1);
        P4EST_ASSERT (mesh->quad_to_face[in_qtoq] == -25);
        mesh->quad_to_quad[in_qtoq] = jl2;
        mesh->quad_to_face[in_qtoq] =
          P4EST_FACES * info->orientation + side2->face;
      }
      if (!side2->is.full.is_ghost) {
        in_qtoq = P4EST_FACES * jl2 + side2->face;
        P4EST_ASSERT (mesh->quad_to_quad[in_qtoq] == -1);
        P4EST_ASSERT (mesh->quad_to_face[in_qtoq] == -25);
        mesh->quad_to_quad[in_qtoq] = jl;
        mesh->quad_to_face[in_qtoq] =
          P4EST_FACES * info->orientation + side->face;
      }
    }
    else {
      /* one of the faces is hanging, rename so it's always side2 */
      swapsides = side->is_hanging;
      if (swapsides) {
        tempside = side;
        side = side2;
        side2 = tempside;
      }
      P4EST_ASSERT (!side->is_hanging && side2->is_hanging);

      /* determine quadrant number for non-hanging large face */
      if (!side->is.full.is_ghost) {
        tree = p4est_tree_array_index (info->p4est->trees, side->treeid);
        jl = side->is.full.quadid + tree->quadrants_offset;
        P4EST_ASSERT (0 <= jl && jl < mesh->local_num_quadrants);
      }
      else {
        P4EST_ASSERT (side->is.full.quad != NULL);
        P4EST_ASSERT (side->is.full.quadid >= 0);
        jl = mesh->local_num_quadrants + side->is.full.quadid;
      }

      /* determine quadrant numbers for all hanging faces */
      for (h = 0; h < P4EST_HALF; ++h) {
        if (!side2->is.hanging.is_ghost[h]) {
          tree = p4est_tree_array_index (info->p4est->trees, side2->treeid);
          jls[h] = side2->is.hanging.quadid[h] + tree->quadrants_offset;
          P4EST_ASSERT (0 <= jls[h] && jls[h] < mesh->local_num_quadrants);
        }
        else {
          P4EST_ASSERT (side2->is.hanging.quad[h] != NULL);
          P4EST_ASSERT (side2->is.hanging.quadid[h] >= 0);
          jls[h] = mesh->local_num_quadrants + side2->is.hanging.quadid[h];
        }
      }

      /* encode quadrant neighborhood */
      if (!side->is.full.is_ghost) {
        in_qtoq = P4EST_FACES * jl + side->face;
        P4EST_ASSERT (mesh->quad_to_quad[in_qtoq] == -1);
        P4EST_ASSERT (mesh->quad_to_face[in_qtoq] == -25);
        halfindex = (p4est_locidx_t) mesh->quad_to_half->elem_count;
        mesh->quad_to_quad[in_qtoq] = halfindex;
        mesh->quad_to_face[in_qtoq] =
          P4EST_FACES * (info->orientation - P4EST_HALF) + side2->face;
        halfentries = (p4est_locidx_t *) sc_array_push (mesh->quad_to_half);
        for (h = 0; h < P4EST_HALF; ++h) {
          halfentries[h] = jls[h];
        }
      }
      for (h = 0; h < P4EST_HALF; ++h) {
        if (!side2->is.hanging.is_ghost[h]) {
          in_qtoq = P4EST_FACES * jls[h] + side2->face;
          P4EST_ASSERT (mesh->quad_to_quad[in_qtoq] == -1);
          P4EST_ASSERT (mesh->quad_to_face[in_qtoq] == -25);
          mesh->quad_to_quad[in_qtoq] = jl;
          mesh->quad_to_face[in_qtoq] =
            P4EST_FACES * (info->orientation + (h + 1) * P4EST_HALF) +
            side->face;
        }
      }
    }
  }
}
Exemplo n.º 19
0
p4est_t            *
p4est_new_points (sc_MPI_Comm mpicomm, p4est_connectivity_t * connectivity,
                  int maxlevel, p4est_quadrant_t * points,
                  p4est_locidx_t num_points, p4est_locidx_t max_points,
                  size_t data_size, p4est_init_t init_fn, void *user_pointer)
{
  int                 mpiret;
  int                 num_procs, rank;
  int                 i, isizet;
  size_t              lcount;
  size_t             *nmemb;
#ifdef P4EST_ENABLE_DEBUG
  size_t              zz;
#endif
  p4est_topidx_t      jt, num_trees;
  p4est_topidx_t      first_tree, last_tree, next_tree;
  p4est_quadrant_t   *first_quad, *next_quad, *quad;
  p4est_quadrant_t    a, b, c, f, l, n;
  p4est_tree_t       *tree;
  p4est_t            *p4est;
  p4est_points_state_t ppstate;

  P4EST_GLOBAL_PRODUCTIONF ("Into " P4EST_STRING
                            "_new_points with max level %d max points %lld\n",
                            maxlevel, (long long) max_points);
  p4est_log_indent_push ();
  P4EST_ASSERT (p4est_connectivity_is_valid (connectivity));
  P4EST_ASSERT (max_points >= -1);

  /* retrieve MPI information */
  mpiret = sc_MPI_Comm_size (mpicomm, &num_procs);
  SC_CHECK_MPI (mpiret);
  mpiret = sc_MPI_Comm_rank (mpicomm, &rank);
  SC_CHECK_MPI (mpiret);

  /* This implementation runs in O(P/p * maxlevel)
   * with P the total number of points, p the number of processors.
   * Two optimizations are possible:
   * 1. At startup remove points that lead to duplicate quadrants.
   * 2. Use complete_region between successive points instead of
   *    the call to refine. This should give O(N/p) * maxlevel
   *    with N the total number of quadrants.
   */

  /* parallel sort the incoming points */
  lcount = (size_t) num_points;
  nmemb = P4EST_ALLOC_ZERO (size_t, num_procs);
  isizet = (int) sizeof (size_t);
  mpiret = sc_MPI_Allgather (&lcount, isizet, sc_MPI_BYTE,
                             nmemb, isizet, sc_MPI_BYTE, mpicomm);
  SC_CHECK_MPI (mpiret);
  sc_psort (mpicomm, points, nmemb, sizeof (p4est_quadrant_t),
            p4est_quadrant_compare_piggy);
  P4EST_FREE (nmemb);
#ifdef P4EST_ENABLE_DEBUG
  first_quad = points;
  for (zz = 1; zz < lcount; ++zz) {
    next_quad = points + zz;
    P4EST_ASSERT (p4est_quadrant_compare_piggy (first_quad, next_quad) <= 0);
    first_quad = next_quad;
  }
#endif

  /* create the p4est */
  p4est = P4EST_ALLOC_ZERO (p4est_t, 1);
  ppstate.points = points;
  ppstate.num_points = num_points;
  ppstate.max_points = max_points;
  ppstate.current = 0;
  ppstate.maxlevel = maxlevel;

  /* assign some data members */
  p4est->data_size = 2 * sizeof (p4est_locidx_t);       /* temporary */
  p4est->user_pointer = &ppstate;
  p4est->connectivity = connectivity;
  num_trees = connectivity->num_trees;

  /* create parallel environment */
  p4est_comm_parallel_env_create (p4est, mpicomm);

  /* allocate memory pools */
  p4est->user_data_pool = sc_mempool_new (p4est->data_size);
  p4est->quadrant_pool = sc_mempool_new (sizeof (p4est_quadrant_t));

  P4EST_GLOBAL_PRODUCTIONF ("New " P4EST_STRING
                            " with %lld trees on %d processors\n",
                            (long long) num_trees, num_procs);

  /* allocate trees */
  p4est->trees = sc_array_new (sizeof (p4est_tree_t));
  sc_array_resize (p4est->trees, num_trees);
  for (jt = 0; jt < num_trees; ++jt) {
    tree = p4est_tree_array_index (p4est->trees, jt);
    sc_array_init (&tree->quadrants, sizeof (p4est_quadrant_t));
    P4EST_QUADRANT_INIT (&tree->first_desc);
    P4EST_QUADRANT_INIT (&tree->last_desc);
    tree->quadrants_offset = 0;
    for (i = 0; i <= P4EST_QMAXLEVEL; ++i) {
      tree->quadrants_per_level[i] = 0;
    }
    for (; i <= P4EST_MAXLEVEL; ++i) {
      tree->quadrants_per_level[i] = -1;
    }
    tree->maxlevel = 0;
  }
  p4est->local_num_quadrants = 0;
  p4est->global_num_quadrants = 0;

  /* create point based partition */
  P4EST_QUADRANT_INIT (&f);
  p4est->global_first_position =
    P4EST_ALLOC_ZERO (p4est_quadrant_t, num_procs + 1);
  if (num_points == 0) {
    P4EST_VERBOSE ("Empty processor");
    first_tree = p4est->first_local_tree = -1;
    first_quad = NULL;
  }
  else {
    /* we are probably not empty */
    if (rank == 0) {
      first_tree = p4est->first_local_tree = 0;
      p4est_quadrant_set_morton (&f, maxlevel, 0);
    }
    else {
      first_tree = p4est->first_local_tree = points->p.which_tree;
      p4est_node_to_quadrant (points, maxlevel, &f);
    }
    first_quad = &f;
  }
  last_tree = p4est->last_local_tree = -2;
  p4est_comm_global_partition (p4est, first_quad);
  first_quad = p4est->global_first_position + rank;
  next_quad = p4est->global_first_position + (rank + 1);
  next_tree = next_quad->p.which_tree;
  if (first_tree >= 0 &&
      p4est_quadrant_is_equal (first_quad, next_quad) &&
      first_quad->p.which_tree == next_quad->p.which_tree) {
    /* if all our points are consumed by the next processor we are empty */
    first_tree = p4est->first_local_tree = -1;
  }
  if (first_tree >= 0) {
    /* we are definitely not empty */
    if (next_quad->x == 0 && next_quad->y == 0
#ifdef P4_TO_P8
        && next_quad->z == 0
#endif
      ) {
      last_tree = p4est->last_local_tree = next_tree - 1;
    }
    else {
      last_tree = p4est->last_local_tree = next_tree;
    }
    P4EST_ASSERT (first_tree <= last_tree);
  }

  /* fill the local trees */
  P4EST_QUADRANT_INIT (&a);
  P4EST_QUADRANT_INIT (&b);
  P4EST_QUADRANT_INIT (&c);
  P4EST_QUADRANT_INIT (&l);
  n = *next_quad;
  n.level = (int8_t) maxlevel;
  for (jt = first_tree; jt <= last_tree; ++jt) {
    int                 onlyone = 0;
    int                 includeb = 0;

    tree = p4est_tree_array_index (p4est->trees, jt);

    /* determine first local quadrant of this tree */
    if (jt == first_tree) {
      a = *first_quad;
      a.level = (int8_t) maxlevel;
      first_quad = next_quad = NULL;    /* free to use further down */
      P4EST_ASSERT (p4est_quadrant_is_valid (&a));
    }
    else {
      p4est_quadrant_set_morton (&a, maxlevel, 0);
      P4EST_ASSERT (jt < next_tree || p4est_quadrant_compare (&a, &n) < 0);
    }

    /* enlarge first local quadrant if possible */
    if (jt < next_tree) {
      while (p4est_quadrant_child_id (&a) == 0 && a.level > 0) {
        p4est_quadrant_parent (&a, &a);
      }
      P4EST_ASSERT (jt == first_tree || a.level == 0);
    }
    else {
      for (c = a; p4est_quadrant_child_id (&c) == 0; a = c) {
        p4est_quadrant_parent (&c, &c);
        p4est_quadrant_last_descendant (&c, &l, maxlevel);
        if (p4est_quadrant_compare (&l, &n) >= 0) {
          break;
        }
      }
      P4EST_ASSERT (a.level > 0);
      P4EST_ASSERT ((p4est_quadrant_last_descendant (&a, &l, maxlevel),
                     p4est_quadrant_compare (&l, &n) < 0));
    }
    p4est_quadrant_first_descendant (&a, &tree->first_desc, P4EST_QMAXLEVEL);

    /* determine largest possible last quadrant of this tree */
    if (jt < next_tree) {
      p4est_quadrant_last_descendant (&a, &l, maxlevel);
      p4est_quadrant_set_morton (&b, 0, 0);
      p4est_quadrant_last_descendant (&b, &b, maxlevel);
      if (p4est_quadrant_is_equal (&l, &b)) {
        onlyone = 1;
      }
      else {
        includeb = 1;
        for (c = b; p4est_quadrant_child_id (&c) == P4EST_CHILDREN - 1; b = c) {
          p4est_quadrant_parent (&c, &c);
          p4est_quadrant_first_descendant (&c, &f, maxlevel);
          if (p4est_quadrant_compare (&l, &f) >= 0) {
            break;
          }
        }
      }
    }
    else {
      b = n;
    }

    /* create a complete tree */
    if (onlyone) {
      quad = p4est_quadrant_array_push (&tree->quadrants);
      *quad = a;
      p4est_quadrant_init_data (p4est, jt, quad, p4est_points_init);
      tree->maxlevel = a.level;
      ++tree->quadrants_per_level[a.level];
    }
    else {
      p4est_complete_region (p4est, &a, 1, &b, includeb,
                             tree, jt, p4est_points_init);
      quad = p4est_quadrant_array_index (&tree->quadrants,
                                         tree->quadrants.elem_count - 1);
    }
    tree->quadrants_offset = p4est->local_num_quadrants;
    p4est->local_num_quadrants += tree->quadrants.elem_count;
    p4est_quadrant_last_descendant (quad, &tree->last_desc, P4EST_QMAXLEVEL);

    /* verification */
#ifdef P4EST_ENABLE_DEBUG
    first_quad = p4est_quadrant_array_index (&tree->quadrants, 0);
    for (zz = 1; zz < tree->quadrants.elem_count; ++zz) {
      next_quad = p4est_quadrant_array_index (&tree->quadrants, zz);
      P4EST_ASSERT (((p4est_locidx_t *) first_quad->p.user_data)[1] ==
                    ((p4est_locidx_t *) next_quad->p.user_data)[0]);
      first_quad = next_quad;
    }
#endif
  }
  if (last_tree >= 0) {
    for (; jt < num_trees; ++jt) {
      tree = p4est_tree_array_index (p4est->trees, jt);
      tree->quadrants_offset = p4est->local_num_quadrants;
    }
  }

  /* compute some member variables */
  p4est->global_first_quadrant = P4EST_ALLOC (p4est_gloidx_t, num_procs + 1);
  p4est_comm_count_quadrants (p4est);

  /* print more statistics */
  P4EST_VERBOSEF ("total local quadrants %lld\n",
                  (long long) p4est->local_num_quadrants);

  P4EST_ASSERT (p4est_is_valid (p4est));
  p4est_log_indent_pop ();
  P4EST_GLOBAL_PRODUCTIONF ("Done " P4EST_STRING
                            "_new_points with %lld total quadrants\n",
                            (long long) p4est->global_num_quadrants);

  /* refine to have one point per quadrant */
  if (max_points >= 0) {
    p4est_refine_ext (p4est, 1, maxlevel, p4est_points_refine,
                      p4est_points_init, NULL);
#ifdef P4EST_ENABLE_DEBUG
    for (jt = first_tree; jt <= last_tree; ++jt) {
      tree = p4est_tree_array_index (p4est->trees, jt);
      first_quad = p4est_quadrant_array_index (&tree->quadrants, 0);
      for (zz = 1; zz < tree->quadrants.elem_count; ++zz) {
        next_quad = p4est_quadrant_array_index (&tree->quadrants, zz);
        P4EST_ASSERT (((p4est_locidx_t *) first_quad->p.user_data)[1] ==
                      ((p4est_locidx_t *) next_quad->p.user_data)[0]);
        first_quad = next_quad;
      }
    }
#endif
  }

  /* initialize user pointer and data size */
  p4est_reset_data (p4est, data_size, init_fn, user_pointer);

  return p4est;
}
Exemplo n.º 20
0
static void
mesh_iter_corner (p4est_iter_corner_info_t * info, void *user_data)
{
  int                 i, j;
  int                 f1, f2, code, orientation;
  int                 fc1, fc2, diagonal;
#ifdef P4_TO_P8
  int                 pref, pset;
#endif
  int                 visited[P4EST_CHILDREN];
  int8_t             *pccorner;
  size_t              cz, zz;
  sc_array_t         *trees;
  p4est_locidx_t      qoffset, qid1, qid2;
  p4est_locidx_t      cornerid_offset, cornerid;
  p4est_locidx_t     *pcquad;
  p4est_mesh_t       *mesh = (p4est_mesh_t *) user_data;
  p4est_iter_corner_side_t *side1, *side2;
  p4est_tree_t       *tree1, *tree2;
  p4est_connectivity_t *conn;

  /* Check the case when the corner does not involve neighbors */
  cz = info->sides.elem_count;
  P4EST_ASSERT (cz > 0);
  P4EST_ASSERT (info->tree_boundary || cz == P4EST_CHILDREN);
  if (cz == 1) {
    return;
  }
  conn = info->p4est->connectivity;
  trees = info->p4est->trees;
  cornerid_offset = mesh->local_num_quadrants + mesh->ghost_num_quadrants;

  if (info->tree_boundary == P4EST_CONNECT_FACE) {
    /* This corner is inside an inter-tree face */
    if (cz == P4EST_HALF) {
      /* This is a tree face boundary, no corner neighbors exist */
      return;
    }
    P4EST_ASSERT (cz == P4EST_CHILDREN);

    /* Process a corner in pairs of diagonal inter-tree neighbors */
    memset (visited, 0, P4EST_CHILDREN * sizeof (int));
    for (i = 0; i < P4EST_HALF; ++i) {
      side1 = side2 = NULL;
      f1 = -1;
      fc1 = -1;
      qid1 = -3;
      for (j = 0; j < P4EST_CHILDREN; ++j) {
        if (visited[j]) {
          continue;
        }

        /* Remember the first side we want to pair up */
        if (side1 == NULL) {
          side1 =
            (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j);
          P4EST_ASSERT (side1->quad != NULL);
          f1 = tree_face_quadrant_corner_face (side1->quad, side1->corner);
          fc1 = p4est_corner_face_corners[side1->corner][f1];
          P4EST_ASSERT (0 <= fc1 && fc1 < P4EST_HALF);
          tree1 = p4est_tree_array_index (trees, side1->treeid);
          qid1 = side1->quadid + (side1->is_ghost ? mesh->local_num_quadrants
                                  : tree1->quadrants_offset);
          visited[j] = 1;
          continue;
        }

        /* Examine a potential second side */
        P4EST_ASSERT (side2 == NULL);
        side2 =
          (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j);
        P4EST_ASSERT (side2->quad != NULL);
        f2 = tree_face_quadrant_corner_face (side2->quad, side2->corner);
        if (side1->treeid == side2->treeid && f1 == f2) {
          /* Periodicity allows for equal trees and unequal faces */
          side2 = NULL;
          continue;
        }

        /* This side as in the opposite tree */
        fc2 = p4est_corner_face_corners[side2->corner][f2];
        P4EST_ASSERT (0 <= fc2 && fc2 < P4EST_HALF);
        code = conn->tree_to_face[P4EST_FACES * side1->treeid + f1];
        orientation = code / P4EST_FACES;
        P4EST_ASSERT (f2 == code % P4EST_FACES);
#ifdef P4_TO_P8
        pref = p8est_face_permutation_refs[f1][f2];
        pset = p8est_face_permutation_sets[pref][orientation];
        diagonal = (p8est_face_permutations[pset][fc1] ^ fc2) == 3;
#else
        diagonal = (fc1 ^ fc2) != orientation;
#endif
        if (!diagonal) {
          side2 = NULL;
          continue;
        }

        /* We have found a diagonally opposite second side */
        tree2 = p4est_tree_array_index (trees, side2->treeid);
        qid2 = side2->quadid + (side2->is_ghost ? mesh->local_num_quadrants
                                : tree2->quadrants_offset);
        if (!side1->is_ghost) {
          P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants);
          P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 +
                                             side1->corner] == -1);
          cornerid = mesh_corner_allocate (mesh, 1, &pcquad, &pccorner);
          mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] =
            cornerid_offset + cornerid;
          *pcquad = qid2;
          *pccorner = side2->corner;
        }
        if (!side2->is_ghost) {
          P4EST_ASSERT (0 <= qid2 && qid2 < mesh->local_num_quadrants);
          P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid2 +
                                             side2->corner] == -1);
          cornerid = mesh_corner_allocate (mesh, 1, &pcquad, &pccorner);
          mesh->quad_to_corner[P4EST_CHILDREN * qid2 + side2->corner] =
            cornerid_offset + cornerid;
          *pcquad = qid1;
          *pccorner = side1->corner;
        }
        visited[j] = 1;
        break;
      }
      P4EST_ASSERT (side1 != NULL && side2 != NULL);
    }
    return;
  }

#ifdef P4_TO_P8
  if (info->tree_boundary == P8EST_CONNECT_EDGE) {
    /* Tree corner neighbors across an edge are not implemented: set to -2 */
    for (zz = 0; zz < cz; ++zz) {
      side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, zz);
      if (!side1->is_ghost) {
        tree1 = p4est_tree_array_index (trees, side1->treeid);
        qid1 = side1->quadid + tree1->quadrants_offset;
        P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants);
        P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 +
                                           side1->corner] == -1);
        mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] = -2;
      }
    }
    return;
  }
#endif

  if (info->tree_boundary == P4EST_CONNECT_CORNER) {
    int                 c1, ncorner[P4EST_DIM];
    int                 nface[P4EST_DIM];
    int                 ignore;
    size_t              z2;
    int8_t             *ccorners;
    p4est_topidx_t      t1, ntree[P4EST_DIM];
    p4est_locidx_t      goodones;
    p4est_locidx_t     *cquads;

    /* Loop through all corner sides, that is the quadrants touching it.  For
     * each of these quadrants, determine the corner sides that can potentially
     * occur by being a face neighbor as well.  Exclude these face neighbors
     * and the quadrant itself, record all others as corner neighbors.
     */
    cquads = P4EST_ALLOC (p4est_locidx_t, cz - 1);
    ccorners = P4EST_ALLOC (int8_t, cz - 1);
    for (zz = 0; zz < cz; ++zz) {
      side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, zz);
      if (!side1->is_ghost) {
        /* We only create corner information for processor-local quadrants */
        t1 = side1->treeid;
        c1 = (int) side1->corner;
        tree1 = p4est_tree_array_index (trees, t1);
        qid1 = side1->quadid + tree1->quadrants_offset;
        P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants);
        P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 + c1] == -1);

        /* Check all quadrant faces that touch this corner */
        for (i = 0; i < P4EST_DIM; ++i) {
          f1 = p4est_corner_faces[c1][i];
          ntree[i] = conn->tree_to_tree[P4EST_FACES * t1 + f1];
          nface[i] = conn->tree_to_face[P4EST_FACES * t1 + f1];
          if (ntree[i] == t1 && nface[i] == f1) {
            /* This is a physical face boundary, no face neighbor present */
            ncorner[i] = -1;
            continue;
          }
          /* We have a face neighbor */
          orientation = nface[i] / P4EST_FACES;
          nface[i] %= P4EST_FACES;
          ncorner[i] = p4est_connectivity_face_neighbor_corner
            (c1, f1, nface[i], orientation);
        }

        /* Go through corner neighbors and collect the true corners */
        goodones = 0;
        for (z2 = 0; z2 < cz; ++z2) {
          if (z2 == zz) {
            /* We do not count ourselves as a neighbor */
            continue;
          }
          ignore = 0;
          side2 =
            (p4est_iter_corner_side_t *) sc_array_index (&info->sides, z2);
          P4EST_ASSERT (side2->corner >= 0);
          for (i = 0; i < P4EST_DIM; ++i) {
            /* Ignore if this is one of the face neighbors' corners */
            if (ncorner[i] == (int) side2->corner &&
                ntree[i] == side2->treeid) {
              ignore = 1;
              break;
            }
          }
          if (ignore) {
            continue;
          }

          /* Record this corner neighbor */
          tree2 = p4est_tree_array_index (trees, side2->treeid);
          qid2 = side2->quadid + (side2->is_ghost ? mesh->local_num_quadrants
                                  : tree2->quadrants_offset);
          cquads[goodones] = qid2;
          ccorners[goodones] = (int) side2->corner;
          ++goodones;
        }
        P4EST_ASSERT ((size_t) goodones < cz);
        if (goodones == 0) {
          continue;
        }

        /* Allocate and fill corner information in the mesh structure */
        cornerid = mesh_corner_allocate (mesh, goodones, &pcquad, &pccorner);
        mesh->quad_to_corner[P4EST_CHILDREN * qid1 + c1] =
          cornerid_offset + cornerid;
        memcpy (pcquad, cquads, goodones * sizeof (p4est_locidx_t));
        memcpy (pccorner, ccorners, goodones * sizeof (int8_t));
      }
    }
    P4EST_FREE (cquads);
    P4EST_FREE (ccorners);
    return;
  }

  /* Process a corner inside the tree in pairs of diagonal neighbors */
  P4EST_ASSERT (!info->tree_boundary);
  side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, 0);
  tree1 = p4est_tree_array_index (trees, side1->treeid);
  qoffset = tree1->quadrants_offset;
  memset (visited, 0, P4EST_CHILDREN * sizeof (int));
  for (i = 0; i < P4EST_HALF; ++i) {
    side1 = side2 = NULL;
    qid1 = -3;
    for (j = 0; j < P4EST_CHILDREN; ++j) {
      if (visited[j]) {
        continue;
      }

      /* Remember the first side we want to pair up */
      if (side1 == NULL) {
        side1 =
          (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j);
        qid1 = side1->quadid +
          (side1->is_ghost ? mesh->local_num_quadrants : qoffset);
        visited[j] = 1;
        continue;
      }

      /* Examine a potential second side */
      P4EST_ASSERT (side2 == NULL);
      side2 =
        (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j);
      P4EST_ASSERT (side1->treeid == side2->treeid);
      if (side1->corner + side2->corner != P4EST_CHILDREN - 1) {
        side2 = NULL;
        continue;
      }

      /* We have found a diagonally opposite second side */
      qid2 = side2->quadid +
        (side2->is_ghost ? mesh->local_num_quadrants : qoffset);
      if (!side1->is_ghost) {
        P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants);
        P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 +
                                           side1->corner] == -1);
        mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] = qid2;
      }
      if (!side2->is_ghost) {
        P4EST_ASSERT (0 <= qid2 && qid2 < mesh->local_num_quadrants);
        P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid2 +
                                           side2->corner] == -1);
        mesh->quad_to_corner[P4EST_CHILDREN * qid2 + side2->corner] = qid1;
      }
      visited[j] = 1;
      break;
    }
    P4EST_ASSERT (side1 != NULL && side2 != NULL);
  }
}
Exemplo n.º 21
0
int
main (int argc, char **argv)
{
  int                 rank;
  int                 num_procs;
  int                 mpiret;
  sc_MPI_Comm         mpicomm;
  p4est_t            *p4est, *copy;
  p4est_connectivity_t *connectivity;
  int                 i;
  p4est_topidx_t      t;
  size_t              qz;
  p4est_locidx_t      num_quadrants_on_last;
  p4est_locidx_t     *num_quadrants_in_proc;
  p4est_gloidx_t     *pertree1, *pertree2;
  p4est_quadrant_t   *quad;
  p4est_tree_t       *tree;
  user_data_t        *user_data;
  int64_t             sum;
  unsigned            crc;

  mpiret = sc_MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);
  mpicomm = sc_MPI_COMM_WORLD;
  mpiret = sc_MPI_Comm_rank (mpicomm, &rank);
  SC_CHECK_MPI (mpiret);

  sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT);

  /* create connectivity and forest structures */
#ifdef P4_TO_P8
  connectivity = p8est_connectivity_new_twocubes ();
#else
  connectivity = p4est_connectivity_new_corner ();
#endif
  p4est = p4est_new_ext (mpicomm, connectivity, 15, 0, 0,
                         sizeof (user_data_t), init_fn, NULL);

  pertree1 = P4EST_ALLOC (p4est_gloidx_t, p4est->connectivity->num_trees + 1);
  pertree2 = P4EST_ALLOC (p4est_gloidx_t, p4est->connectivity->num_trees + 1);
  num_procs = p4est->mpisize;
  num_quadrants_in_proc = P4EST_ALLOC (p4est_locidx_t, num_procs);

  /* refine and balance to make the number of elements interesting */
  test_pertree (p4est, NULL, pertree1);
  p4est_refine (p4est, 1, refine_fn, init_fn);
  test_pertree (p4est, NULL, pertree1);

  /* Set an arbitrary partition.
   *
   * Since this is just a test we assume the global number of
   * quadrants will fit in an int32_t
   */
  num_quadrants_on_last = (p4est_locidx_t) p4est->global_num_quadrants;
  for (i = 0; i < num_procs - 1; ++i) {
    num_quadrants_in_proc[i] = (p4est_locidx_t) i + 1;  /* type ok */
    num_quadrants_on_last -= (p4est_locidx_t) i + 1;    /* type ok */
  }
  num_quadrants_in_proc[num_procs - 1] = num_quadrants_on_last;
  SC_CHECK_ABORT (num_quadrants_on_last > 0,
                  "Negative number of quadrants on the last processor");

  /* Save a checksum of the original forest */
  crc = p4est_checksum (p4est);

  /* partition the forest */
  (void) p4est_partition_given (p4est, num_quadrants_in_proc);
  test_pertree (p4est, pertree1, pertree2);

  /* Double check that we didn't loose any quads */
  SC_CHECK_ABORT (crc == p4est_checksum (p4est),
                  "bad checksum, missing a quad");

  /* count the actual number of quadrants per proc */
  SC_CHECK_ABORT (num_quadrants_in_proc[rank]
                  == p4est->local_num_quadrants,
                  "partition failed, wrong number of quadrants");

  /* check user data content */
  for (t = p4est->first_local_tree; t <= p4est->last_local_tree; ++t) {
    tree = p4est_tree_array_index (p4est->trees, t);
    for (qz = 0; qz < tree->quadrants.elem_count; ++qz) {
      quad = p4est_quadrant_array_index (&tree->quadrants, qz);
      user_data = (user_data_t *) quad->p.user_data;
      sum = quad->x + quad->y + quad->level;

      SC_CHECK_ABORT (user_data->a == t, "bad user_data, a");
      SC_CHECK_ABORT (user_data->sum == sum, "bad user_data, sum");
    }
  }

  /* do a weighted partition with uniform weights */
  p4est_partition (p4est, 0, weight_one);
  test_pertree (p4est, pertree1, pertree2);
  SC_CHECK_ABORT (crc == p4est_checksum (p4est),
                  "bad checksum after uniformly weighted partition");

  /* copy the p4est */
  copy = p4est_copy (p4est, 1);
  SC_CHECK_ABORT (crc == p4est_checksum (copy), "bad checksum after copy");

  /* do a weighted partition with many zero weights */
  weight_counter = 0;
  weight_index = (rank == 1) ? 1342 : 0;
  p4est_partition (copy, 0, weight_once);
  test_pertree (copy, pertree1, pertree2);
  SC_CHECK_ABORT (crc == p4est_checksum (copy),
                  "bad checksum after unevenly weighted partition 1");

  /* do a weighted partition with many zero weights */
  weight_counter = 0;
  weight_index = 0;
  p4est_partition (copy, 0, weight_once);
  test_pertree (copy, pertree1, pertree2);
  SC_CHECK_ABORT (crc == p4est_checksum (copy),
                  "bad checksum after unevenly weighted partition 2");

  /* do a weighted partition with many zero weights
   *
   * Since this is just a test we assume the local number of
   * quadrants will fit in an int
   */
  weight_counter = 0;
  weight_index =
    (rank == num_procs - 1) ? ((int) copy->local_num_quadrants - 1) : 0;
  p4est_partition (copy, 0, weight_once);
  test_pertree (copy, pertree1, pertree2);
  SC_CHECK_ABORT (crc == p4est_checksum (copy),
                  "bad checksum after unevenly weighted partition 3");

  /* check user data content */
  for (t = copy->first_local_tree; t <= copy->last_local_tree; ++t) {
    tree = p4est_tree_array_index (copy->trees, t);
    for (qz = 0; qz < tree->quadrants.elem_count; ++qz) {
      quad = p4est_quadrant_array_index (&tree->quadrants, qz);
      user_data = (user_data_t *) quad->p.user_data;
      sum = quad->x + quad->y + quad->level;

      SC_CHECK_ABORT (user_data->a == t, "bad user_data, a");
      SC_CHECK_ABORT (user_data->sum == sum, "bad user_data, sum");
    }
  }

  /* Add another test.  Overwrites pertree1, pertree2 */
  test_partition_circle (mpicomm, connectivity, pertree1, pertree2);

  /* clean up and exit */
  P4EST_FREE (pertree1);
  P4EST_FREE (pertree2);
  P4EST_FREE (num_quadrants_in_proc);
  p4est_destroy (p4est);
  p4est_destroy (copy);
  p4est_connectivity_destroy (connectivity);
  sc_finalize ();

  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
Exemplo n.º 22
0
p4est_gloidx_t     *
p6est_lnodes_get_column_labels (p6est_t * p6est, p8est_lnodes_t * lnodes)
{
  p4est_gloidx_t     *labels;
  p4est_gloidx_t      num_cols = 0;
  p4est_gloidx_t      global_num_cols = 0;
  p4est_topidx_t      jt;
  p4est_tree_t       *tree;
  sc_array_t         *tquadrants;
  p4est_quadrant_t   *col;
  size_t              zz, first, last;
  p4est_locidx_t      lfirst, llast, lk;
  int                 stride = lnodes->degree + 1;
  int                 vnodes = lnodes->vnodes;
  int                 mpiret, i;

  labels = P4EST_ALLOC (p4est_gloidx_t, lnodes->owned_count);
  memset (labels, -1, lnodes->owned_count * sizeof (*labels));

  for (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) {
      col = p4est_quadrant_array_index (tquadrants, zz);
      P6EST_COLUMN_GET_RANGE (col, &first, &last);
      lfirst = (p4est_locidx_t) first;
      llast = (p4est_locidx_t) last;
      for (i = 0; i < vnodes; i += stride) {
        p4est_locidx_t      fnid = lnodes->element_nodes[vnodes * lfirst + i];
        p4est_locidx_t      lnid =
          lnodes->element_nodes[vnodes * (llast - 1) + i + (stride - 1)];
        P4EST_ASSERT (lnid >= 0);
        P4EST_ASSERT (lnid >= fnid);
        P4EST_ASSERT (fnid < lnodes->num_local_nodes);
        if (lnid < lnodes->owned_count) {
          P4EST_ASSERT (fnid < lnodes->owned_count);
          if (labels[fnid] < 0) {
            for (lk = fnid; lk <= lnid; lk++) {
              labels[lk] = num_cols;
            }
            num_cols++;
          }
        }
      }
    }
  }

  mpiret =
    sc_MPI_Exscan (&num_cols, &global_num_cols, 1, P4EST_MPI_GLOIDX,
                   sc_MPI_SUM, lnodes->mpicomm);
  SC_CHECK_MPI (mpiret);

  if (!p6est->mpirank) {
    global_num_cols = 0;
  }

  for (lk = 0; lk < lnodes->owned_count; lk++) {
    labels[lk] += global_num_cols;
  }

#if 0
  {
    sc_array_t          view;

    sc_array_init_data (&view, labels, sizeof (*labels),
                        (size_t) lnodes->num_local_nodes);

    p6est_lnodes_share_owned (&view, lnodes);
  }
#endif

  for (lk = 0; lk < lnodes->owned_count; lk++) {
    P4EST_ASSERT (labels[lk] >= 0);
  }

  return labels;
}
Exemplo n.º 23
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;
}
Exemplo n.º 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;
}
Exemplo n.º 25
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);
}
Exemplo n.º 26
0
static void
p4est_coarsen_old (p4est_t * p4est, int coarsen_recursive,
                   p4est_coarsen_t coarsen_fn, p4est_init_t init_fn)
{
#ifdef P4EST_ENABLE_DEBUG
  size_t              data_pool_size;
#endif
  int                 i, maxlevel;
  int                 couldbegood;
  size_t              zz;
  size_t              incount, removed;
  size_t              cidz, first, last, rest, before;
  p4est_locidx_t      num_quadrants, prev_offset;
  p4est_topidx_t      jt;
  p4est_tree_t       *tree;
  p4est_quadrant_t   *c[P4EST_CHILDREN];
  p4est_quadrant_t   *cfirst, *clast;
  sc_array_t         *tquadrants;

  P4EST_GLOBAL_PRODUCTIONF ("Into " P4EST_STRING
                            "_coarsen_old with %lld total quadrants\n",
                            (long long) p4est->global_num_quadrants);
  p4est_log_indent_push ();
  P4EST_ASSERT (p4est_is_valid (p4est));

  /* loop over all local trees */
  prev_offset = 0;
  for (jt = p4est->first_local_tree; jt <= p4est->last_local_tree; ++jt) {
    tree = p4est_tree_array_index (p4est->trees, jt);
    tquadrants = &tree->quadrants;
#ifdef P4EST_ENABLE_DEBUG
    data_pool_size = 0;
    if (p4est->user_data_pool != NULL) {
      data_pool_size = p4est->user_data_pool->elem_count;
    }
#endif
    removed = 0;

    /* initial log message for this tree */
    P4EST_VERBOSEF ("Into coarsen tree %lld with %llu\n", (long long) jt,
                    (unsigned long long) tquadrants->elem_count);

    /* Initialize array indices.
       If children are coarsened, the array will have an empty window.
       first   index of the first child to be considered
       last    index of the last child before the hole in the array
       before  number of children before the hole in the array
       rest    index of the first child after the hole in the array
     */
    first = last = 0;
    before = rest = 1;

    /* run through the array and coarsen recursively */
    incount = tquadrants->elem_count;
    while (rest + P4EST_CHILDREN - 1 - before < incount) {
      couldbegood = 1;
      for (zz = 0; zz < P4EST_CHILDREN; ++zz) {
        if (zz < before) {
          c[zz] = p4est_quadrant_array_index (tquadrants, first + zz);
          if (zz != (size_t) p4est_quadrant_child_id (c[zz])) {
            couldbegood = 0;
            break;
          }
        }
        else {
          c[zz] = p4est_quadrant_array_index (tquadrants, rest + zz - before);
        }
      }
      if (couldbegood && p4est_quadrant_is_familypv (c) &&
          coarsen_fn (p4est, jt, c)) {
        /* coarsen now */
        for (zz = 0; zz < P4EST_CHILDREN; ++zz) {
          p4est_quadrant_free_data (p4est, c[zz]);
        }
        tree->quadrants_per_level[c[0]->level] -= P4EST_CHILDREN;
        cfirst = c[0];
        p4est_quadrant_parent (c[0], cfirst);
        p4est_quadrant_init_data (p4est, jt, cfirst, init_fn);
        tree->quadrants_per_level[cfirst->level] += 1;
        p4est->local_num_quadrants -= P4EST_CHILDREN - 1;
        removed += P4EST_CHILDREN - 1;

        rest += P4EST_CHILDREN - before;
        if (coarsen_recursive) {
          last = first;
          cidz = (size_t) p4est_quadrant_child_id (cfirst);
          if (cidz > first)
            first = 0;
          else
            first -= cidz;
        }
        else {
          /* don't coarsen again, move the counters and the hole */
          P4EST_ASSERT (first == last && before == 1);
          if (rest < incount) {
            ++first;
            cfirst = p4est_quadrant_array_index (tquadrants, first);
            clast = p4est_quadrant_array_index (tquadrants, rest);
            *cfirst = *clast;
            last = first;
            ++rest;
          }
        }
      }
      else {
        /* do nothing, just move the counters and the hole */
        ++first;
        if (first > last) {
          if (first != rest) {
            cfirst = p4est_quadrant_array_index (tquadrants, first);
            clast = p4est_quadrant_array_index (tquadrants, rest);
            *cfirst = *clast;
          }
          last = first;
          ++rest;
        }
      }
      before = last - first + 1;
    }

    /* adjust final array size */
    first = last;
    if (first + 1 < rest) {
      while (rest < incount) {
        ++first;
        cfirst = p4est_quadrant_array_index (tquadrants, first);
        clast = p4est_quadrant_array_index (tquadrants, rest);
        *cfirst = *clast;
        ++rest;
      }
      sc_array_resize (tquadrants, first + 1);
    }

    /* compute maximum level */
    maxlevel = 0;
    num_quadrants = 0;
    for (i = 0; i <= P4EST_QMAXLEVEL; ++i) {
      P4EST_ASSERT (tree->quadrants_per_level[i] >= 0);
      num_quadrants += tree->quadrants_per_level[i];    /* same type */
      if (tree->quadrants_per_level[i] > 0) {
        maxlevel = i;
      }
    }
    tree->maxlevel = (int8_t) maxlevel;
    tree->quadrants_offset = prev_offset;
    prev_offset += num_quadrants;

    /* do some sanity checks */
    P4EST_ASSERT (num_quadrants == (p4est_locidx_t) tquadrants->elem_count);
    P4EST_ASSERT (tquadrants->elem_count == incount - removed);
    if (p4est->user_data_pool != NULL) {
      P4EST_ASSERT (data_pool_size - removed ==
                    p4est->user_data_pool->elem_count);
    }
    P4EST_ASSERT (p4est_tree_is_sorted (tree));
    P4EST_ASSERT (p4est_tree_is_complete (tree));

    /* final log message for this tree */
    P4EST_VERBOSEF ("Done coarsen tree %lld now %llu\n", (long long) jt,
                    (unsigned long long) tquadrants->elem_count);
  }
  if (p4est->last_local_tree >= 0) {
    for (; jt < p4est->connectivity->num_trees; ++jt) {
      tree = p4est_tree_array_index (p4est->trees, jt);
      tree->quadrants_offset = p4est->local_num_quadrants;
    }
  }

  /* compute global number of quadrants */
  p4est_comm_count_quadrants (p4est);

  P4EST_ASSERT (p4est_is_valid (p4est));
  p4est_log_indent_pop ();
  P4EST_GLOBAL_PRODUCTIONF ("Done " P4EST_STRING
                            "_coarsen_old with %lld total quadrants\n",
                            (long long) p4est->global_num_quadrants);
}
Exemplo n.º 27
0
int
main (int argc, char *argv[])
{
  MPI_Comm comm = MPI_COMM_WORLD;
  p4est_t *p4est;
  p4est_connectivity_t *conn;
  p4est_ghost_t *ghost_layer;
  p4est_lnodes_t *lnodes;
  int rank;
  const int degree = 1;

  BFAM_MPI_CHECK(MPI_Init(&argc,&argv));
  BFAM_MPI_CHECK(MPI_Comm_rank(comm, &rank));

  bfam_log_init(rank, stdout, BFAM_LL_DEFAULT);
  bfam_signal_handler_set();

  sc_init(comm, 0, 0, NULL, SC_LP_DEFAULT);
  p4est_init(NULL, SC_LP_DEFAULT);

  conn = p4est_connectivity_new_corner();
  p4est = p4est_new_ext(comm, conn, 0, 0, 0, 0, NULL, NULL);

  refine_level = 1;
  p4est_refine(p4est, 1, refine_fn, NULL);
  p4est_balance(p4est, P4EST_CONNECT_FACE, NULL);
  p4est_partition(p4est, 1, NULL);

  p4est_vtk_write_file(p4est, NULL, "mesh");

  ghost_layer = p4est_ghost_new(p4est, P4EST_CONNECT_FULL);
  lnodes = p4est_lnodes_new(p4est, ghost_layer, degree);


  /*
   * Output the mesh.  It can be read using something like following command:
   *
   * mpirun -np 3 ./bfam_exam_p4est | grep MESH | sort -n -k 2 | sort -n -k 5 | gvim -
   */
  fflush(stdout);
  BFAM_MPI_CHECK(MPI_Barrier(comm));
  BFAM_ROOT_INFO("MESH 0 ------------ Mesh Begin ------------");
  BFAM_ROOT_INFO("MESH 1 degree  = %d", lnodes->degree);
  BFAM_ROOT_INFO("MESH 2 vnodes = %d", lnodes->vnodes);
  BFAM_INFO("MESH 3 num_local_elements  = %jd", (intmax_t)lnodes->num_local_elements);
  BFAM_INFO("MESH 4 num_local_nodes = %jd", (intmax_t)lnodes->num_local_nodes);
  BFAM_INFO("MESH 5 owned_count = %jd", (intmax_t)lnodes->owned_count);
  BFAM_INFO("MESH 6 global_offset = %jd", (intmax_t)lnodes->global_offset);


  sc_array_t *global_nodes = sc_array_new(sizeof (p4est_gloidx_t));
  sc_array_resize(global_nodes, lnodes->num_local_nodes);
  for(size_t zz = 0; zz < global_nodes->elem_count; ++zz)
  {
    *((p4est_gloidx_t *) sc_array_index(global_nodes, zz)) =
      p4est_lnodes_global_index(lnodes, zz);
  }

  p4est_lnodes_share_owned(global_nodes, lnodes);

  for(size_t zz = 0; zz < global_nodes->elem_count; ++zz)
  {
    const p4est_gloidx_t gn =
      *((p4est_gloidx_t *)sc_array_index(global_nodes, zz));
    SC_CHECK_ABORT (gn == p4est_lnodes_global_index(lnodes, zz),
        "Lnodes: bad global index across procesors");
    BFAM_INFO("MESH 7 global_nodes[%zu] = %jd", zz, (intmax_t)gn);
  }

  sc_array_destroy(global_nodes);

  p4est_topidx_t  flt = p4est->first_local_tree;
  p4est_topidx_t  llt = p4est->last_local_tree;

  p4est_locidx_t elid, elnid;
  p4est_topidx_t t;
  const double *v = conn->vertices;
  const p4est_topidx_t *tree_to_vertex = conn->tree_to_vertex;
  for(elid = 0, elnid = 0, t = flt; t <= llt; ++t)
  {
    p4est_tree_t *tree = p4est_tree_array_index(p4est->trees, t);
    const size_t count = tree->quadrants.elem_count;
    p4est_topidx_t vt[P4EST_CHILDREN];

    for (int c = 0; c < P4EST_CHILDREN; ++c)
    {
      vt[c] = tree_to_vertex[t * P4EST_CHILDREN + c];
    }

    for (size_t zz = 0; zz < count; ++zz, ++elid)
    {
      p4est_quadrant_t *q = p4est_quadrant_array_index(&tree->quadrants, zz);

      for(int jind = 0; jind < degree + 1; ++jind)
      {
        for(int iind = 0; iind < degree + 1; ++iind, ++elnid)
        {
          double xyz[3];
          for (int j = 0; j < 3; ++j)
          {

            const p4est_qcoord_t len  = P4EST_QUADRANT_LEN(q->level);
            const double         rlen = (double) P4EST_ROOT_LEN;
            const double         deg  = (double) degree;
            const double         qlen = ((double) len) / rlen;

            const double eta_x =
              ((double) q->x) / rlen + (((double) iind) / deg) * qlen;
            const double eta_y =
              ((double) q->y) / rlen + (((double) jind) / deg) * qlen;

            xyz[j] = ((1. - eta_y) * ((1. - eta_x) * v[3 * vt[0] + j] +
                                            eta_x  * v[3 * vt[1] + j]) +
                            eta_y  * ((1. - eta_x) * v[3 * vt[2] + j] +
                                            eta_x  * v[3 * vt[3] + j]));
          }

          const p4est_locidx_t nid = lnodes->element_nodes[elnid];

          BFAM_INFO(
              "MESH 8 local_node[%03jd] = %03jd ( %25.16e %25.16e %25.16e )",
              (intmax_t)elnid, (intmax_t)nid, xyz[0], xyz[1], xyz[2]);
        }
      }
    }
  }


  BFAM_ROOT_INFO("MESH 9 ------------ Mesh End ------------");




  p4est_lnodes_destroy(lnodes);
  p4est_ghost_destroy(ghost_layer);
  p4est_destroy(p4est);
  p4est_connectivity_destroy(conn);

  sc_finalize();
  BFAM_MPI_CHECK(MPI_Finalize());

  return EXIT_SUCCESS;
}