Example #1
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;
        }
      }
    }
  }
}
Example #2
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;
}