Example #1
0
void
p6est_profile_balance_local (p6est_profile_t * profile)
{
  p4est_lnodes_t     *lnodes = profile->lnodes;
  p4est_locidx_t      nln, nle;
  p4est_locidx_t     *en, (*lr)[2];
  sc_array_t         *lc;
  int                 i, j;
  p4est_locidx_t      nidx, enidx, eidx;
  p8est_connect_type_t btype = profile->btype;
  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;
  sc_array_t          testprof;
  int                 any_prof_change;
  int                 any_local_change;
  int                 evenodd = profile->evenodd;
  p4est_qcoord_t      diff = profile->diff;

  P4EST_ASSERT (profile->lnodes->degree == 2);

  if (btype == P8EST_CONNECT_FACE) {
    hbtype = P4EST_CONNECT_FACE;
  }
  else {
    hbtype = P4EST_CONNECT_FULL;
  }
  en = lnodes->element_nodes;
  nln = lnodes->num_local_nodes;
  nle = lnodes->num_local_elements;
  lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges;
  lc = profile->lnode_columns;
  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));

  do {
    /* We read from evenodd and write to evenodd ^ 1 */
    memset (&(profile->lnode_changed[evenodd ^ 1][0]), 0, sizeof (int) * nln);
    P4EST_GLOBAL_VERBOSE ("p6est_balance local loop\n");

    any_local_change = 0;
    for (eidx = 0, enidx = 0; eidx < nle; eidx++) {
      p4est_locidx_t      start_enidx = enidx;
      nidx = en[start_enidx + P4EST_INSUL / 2];
      P4EST_ASSERT (lr[nidx][1]);
      sc_array_init_view (&oldprof, lc, lr[nidx][0], lr[nidx][1]);
      thisprof = &oldprof;
      any_prof_change = 0;
      for (j = 0; j < 3; j++) {
        for (i = 0; i < 3; i++, enidx++) {
          nidx = en[enidx];
          if (!profile->lnode_changed[evenodd][nidx]) {
            /* if the profile hasn't changed since I wrote to it, there's no
             * need to balance against it */
            continue;
          }
          if (i != 1 && j != 1) {
            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;
            }
          }
          if (i == 1 && j == 1) {
            /* no need to further balance against oneself */
            continue;
          }
          P4EST_ASSERT (lr[nidx][1]);
          P4EST_ASSERT (profile->enode_counts[enidx] <= lr[nidx][1]);
          if (profile->enode_counts[enidx] == lr[nidx][1]) {
            /* if the profile hasn't changed since I wrote to it, there's no
             * need to balance against it */
            continue;
          }
          sc_array_init_view (&testprof, lc, lr[nidx][0], lr[nidx][1]);
          p6est_profile_union (thisprof, &testprof, work);
          if (work->elem_count > thisprof->elem_count) {
            P4EST_ASSERT (profile->lnode_changed[evenodd][nidx]);
            any_prof_change = 1;
            sc_array_copy (selfprof, work);
            thisprof = selfprof;
          }
        }
      }

      if (any_prof_change) {
        P4EST_ASSERT (thisprof == selfprof);
        P4EST_ASSERT (selfprof->elem_count > oldprof.elem_count);
        /* update */
        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);
        }
        enidx = start_enidx;
        for (j = 0; j < 3; j++) {
          for (i = 0; i < 3; i++, enidx++) {
            thisprof = NULL;
            nidx = en[enidx];
            if (i != 1 && j != 1) {
              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 == 1 && j == 1) {
              thisprof = selfprof;
            }
            else {
              thisprof = faceprof;
            }
            P4EST_ASSERT (lr[nidx][1]);
            /* 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]);
            if (i == 1 && j == 1) {
              sc_array_copy (work, thisprof);
            }
            else {
              p6est_profile_union (thisprof, &oldprof, work);
            }
            if (work->elem_count > oldprof.elem_count) {
              if (!(i == 1 && j == 1)) {        /* we don't count changing self */
                profile->lnode_changed[evenodd ^ 1][nidx] = 1;
                any_local_change = 1;
              }
              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);
            }
            profile->enode_counts[enidx] = lr[nidx][1];
          }
        }
      }
    }
    p6est_profile_compress (profile);
    evenodd ^= 1;
  } while (any_local_change);

  profile->evenodd = evenodd;
  sc_array_destroy (selfprof);
  sc_array_destroy (faceprof);
  sc_array_destroy (cornerprof);
  sc_array_destroy (work);
}
Example #2
0
int
main (int argc, char **argv)
{
  p4est_quadrant_t    root;
  p4est_quadrant_t    p;
  p4est_quadrant_t    q;
  p4est_quadrant_t    desc;
  int                 face, corner;
#ifndef P4_TO_P8
  int                 maxlevel = 9;
#else
  int                 edge;
  int                 maxlevel = 6;
#endif
  int                 mpiret, mpisize, mpirank;
  sc_MPI_Comm         mpicomm;
  uint64_t            i, ifirst, ilast;
  int                 level;
  sc_array_t         *seeds, *seeds_check;
  int                 testval;
  int                 checkval;
  int                 j, nrand = 1000;

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

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

  seeds = sc_array_new (sizeof (p4est_quadrant_t));
  seeds_check = sc_array_new (sizeof (p4est_quadrant_t));

  memset (&root, 0, sizeof (p4est_quadrant_t));
  root.level = 2;
  root.x = P4EST_QUADRANT_LEN (2);
  root.y = P4EST_QUADRANT_LEN (2);
#ifdef P4_TO_P8
  root.z = P4EST_QUADRANT_LEN (2);
#endif
  P4EST_QUADRANT_INIT (&p);
  P4EST_QUADRANT_INIT (&q);

#if 1
  for (face = 0; face < P4EST_FACES; face++) {
    p4est_quadrant_face_neighbor (&root, face ^ 1, &p);
    P4EST_GLOBAL_VERBOSEF ("Testing face %d\n", face);
    for (level = 4; level <= maxlevel; level++) {
      P4EST_GLOBAL_VERBOSEF (" level %d\n", level);
      p4est_quadrant_first_descendant (&root, &desc, level);
      ifirst = p4est_quadrant_linear_id (&desc, level);
      p4est_quadrant_last_descendant (&root, &desc, level);
      ilast = p4est_quadrant_linear_id (&desc, level);
      for (i = ifirst; i <= ilast; i += P4EST_CHILDREN) {
        p4est_quadrant_set_morton (&q, level, i);
#ifndef P4_TO_P8
        testval = p4est_balance_seeds_face (&q, &p, face, P4EST_CONNECT_FACE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p4est_balance_seeds_face error");
        compare_seeds (seeds, seeds_check);
#else
        testval = p4est_balance_seeds_face (&q, &p, face, P8EST_CONNECT_FACE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_face error");
        compare_seeds (seeds, seeds_check);
        testval = p4est_balance_seeds_face (&q, &p, face, P8EST_CONNECT_EDGE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_face error");
        compare_seeds (seeds, seeds_check);
#endif
        testval = p4est_balance_seeds_face (&q, &p, face, P4EST_CONNECT_FULL,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FULL,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p4est_balance_seeds_face error");
        compare_seeds (seeds, seeds_check);
      }
    }
    if (!face) {
      P4EST_GLOBAL_VERBOSE (" random levels\n");
      for (j = 0; j < (int) nrand; j++) {
        level = ((random ()) % (P4EST_QMAXLEVEL - maxlevel)) + maxlevel + 1;
        p4est_quadrant_first_descendant (&root, &desc, level);
        ifirst = p4est_quadrant_linear_id (&desc, level);
        p4est_quadrant_last_descendant (&root, &desc, level);
        ilast = p4est_quadrant_linear_id (&desc, level);
        i = ((random ()) % (ilast + 1 - ifirst)) + ifirst;
        p4est_quadrant_set_morton (&q, level, i);
#ifndef P4_TO_P8
        testval = p4est_balance_seeds_face (&q, &p, face, P4EST_CONNECT_FACE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p4est_balance_seeds_face error");
        compare_seeds (seeds, seeds_check);
#else
        testval = p4est_balance_seeds_face (&q, &p, face, P8EST_CONNECT_FACE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_face error");
        compare_seeds (seeds, seeds_check);
        testval = p4est_balance_seeds_face (&q, &p, face, P8EST_CONNECT_EDGE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_face error");
        compare_seeds (seeds, seeds_check);
#endif
        testval = p4est_balance_seeds_face (&q, &p, face, P4EST_CONNECT_FULL,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FULL,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p4est_balance_seeds_face error");
        compare_seeds (seeds, seeds_check);
      }
    }
  }

#ifdef P4_TO_P8
  for (edge = 0; edge < P8EST_EDGES; edge++) {
    p8est_quadrant_edge_neighbor (&root, edge ^ 3, &p);
    P4EST_GLOBAL_VERBOSEF ("Testing edge %d\n", edge);
    for (level = 4; level <= maxlevel; level++) {
      P4EST_GLOBAL_VERBOSEF (" level %d\n", level);
      p4est_quadrant_first_descendant (&root, &desc, level);
      ifirst = p4est_quadrant_linear_id (&desc, level);
      p4est_quadrant_last_descendant (&root, &desc, level);
      ilast = p4est_quadrant_linear_id (&desc, level);
      for (i = ifirst; i <= ilast; i += P4EST_CHILDREN) {
        p4est_quadrant_set_morton (&q, level, i);
        testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_FACE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_edge error");
        compare_seeds (seeds, seeds_check);
        testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_EDGE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_edge error");
        compare_seeds (seeds, seeds_check);
        testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_FULL,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FULL,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_edge error");
        compare_seeds (seeds, seeds_check);
      }
    }
    if (!edge) {
      P4EST_GLOBAL_VERBOSE (" random levels\n");
      for (j = 0; j < (int) nrand; j++) {
        level = ((random ()) % (P4EST_QMAXLEVEL - maxlevel)) + maxlevel + 1;
        p4est_quadrant_first_descendant (&root, &desc, level);
        ifirst = p4est_quadrant_linear_id (&desc, level);
        p4est_quadrant_last_descendant (&root, &desc, level);
        ilast = p4est_quadrant_linear_id (&desc, level);
        i = ((random ()) % (ilast + 1 - ifirst)) + ifirst;
        p4est_quadrant_set_morton (&q, level, i);
        testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_FACE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_edge error");
        compare_seeds (seeds, seeds_check);
        testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_EDGE,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_edge error");
        compare_seeds (seeds, seeds_check);
        testval = p8est_balance_seeds_edge (&q, &p, edge, P8EST_CONNECT_FULL,
                                            seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FULL,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_edge error");
        compare_seeds (seeds, seeds_check);
      }
    }
  }
#endif
#endif

  for (corner = 0; corner < P4EST_FACES; corner++) {
    p4est_quadrant_corner_neighbor (&root, corner ^ (P4EST_CHILDREN - 1), &p);
    P4EST_GLOBAL_VERBOSEF ("Testing corner %d\n", corner);
    for (level = 4; level <= maxlevel; level++) {
      P4EST_GLOBAL_VERBOSEF (" level %d\n", level);
      p4est_quadrant_first_descendant (&root, &desc, level);
      ifirst = p4est_quadrant_linear_id (&desc, level);
      p4est_quadrant_last_descendant (&root, &desc, level);
      ilast = p4est_quadrant_linear_id (&desc, level);
      for (i = ifirst; i <= ilast; i += P4EST_CHILDREN) {
        p4est_quadrant_set_morton (&q, level, i);
#ifndef P4_TO_P8
        testval =
          p4est_balance_seeds_corner (&q, &p, corner, P4EST_CONNECT_FACE,
                                      seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p4est_balance_seeds_corner error");
        compare_seeds (seeds, seeds_check);
#else
        testval = p4est_balance_seeds_corner (&q, &p, corner,
                                              P8EST_CONNECT_FACE, seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_corner error");
        compare_seeds (seeds, seeds_check);
        testval =
          p4est_balance_seeds_corner (&q, &p, corner, P8EST_CONNECT_EDGE,
                                      seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_corner error");
        compare_seeds (seeds, seeds_check);
#endif
        testval =
          p4est_balance_seeds_corner (&q, &p, corner, P4EST_CONNECT_FULL,
                                      seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FULL,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p4est_balance_seeds_corner error");
        compare_seeds (seeds, seeds_check);
      }
    }
    if (!corner) {
      P4EST_GLOBAL_VERBOSE (" random levels\n");
      for (j = 0; j < (int) nrand; j++) {
        level = ((random ()) % (P4EST_QMAXLEVEL - maxlevel)) + maxlevel + 1;
        p4est_quadrant_first_descendant (&root, &desc, level);
        ifirst = p4est_quadrant_linear_id (&desc, level);
        p4est_quadrant_last_descendant (&root, &desc, level);
        ilast = p4est_quadrant_linear_id (&desc, level);
        i = ((random ()) % (ilast + 1 - ifirst)) + ifirst;
        p4est_quadrant_set_morton (&q, level, i);
#ifndef P4_TO_P8
        testval =
          p4est_balance_seeds_corner (&q, &p, corner, P4EST_CONNECT_FACE,
                                      seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p4est_balance_seeds_corner error");
        compare_seeds (seeds, seeds_check);
#else
        testval = p4est_balance_seeds_corner (&q, &p, corner,
                                              P8EST_CONNECT_FACE, seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_FACE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_corner error");
        compare_seeds (seeds, seeds_check);
        testval =
          p4est_balance_seeds_corner (&q, &p, corner, P8EST_CONNECT_EDGE,
                                      seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P8EST_CONNECT_EDGE,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p8est_balance_seeds_corner error");
        compare_seeds (seeds, seeds_check);
#endif
        testval =
          p4est_balance_seeds_corner (&q, &p, corner, P4EST_CONNECT_FULL,
                                      seeds);
        standard_seeds (seeds);
        checkval = check_balance_seeds (&q, &p, P4EST_CONNECT_FULL,
                                        seeds_check);
        SC_CHECK_ABORT (testval == checkval,
                        "p4est_balance_seeds_corner error");
        compare_seeds (seeds, seeds_check);
      }
    }
  }

  sc_array_destroy (seeds);
  sc_array_destroy (seeds_check);

  sc_finalize ();

  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}