예제 #1
0
파일: sc.c 프로젝트: johannrudi/libsc
void
sc_memory_check (int package)
{
  sc_package_t       *p;

  if (package == -1) {
    SC_CHECK_ABORT (default_rc_active == 0, "Leftover references (default)");
    if (default_abort_mismatch) {
      SC_CHECK_ABORT (default_malloc_count == default_free_count,
                      "Memory balance (default)");
    }
    else if (default_malloc_count != default_free_count) {
      SC_GLOBAL_LERROR ("Memory balance (default)\n");
    }
  }
  else {
    SC_ASSERT (sc_package_is_registered (package));
    p = sc_packages + package;
    SC_CHECK_ABORTF (p->rc_active == 0, "Leftover references (%s)", p->name);
    if (p->abort_mismatch) {
      SC_CHECK_ABORTF (p->malloc_count == p->free_count,
                       "Memory balance (%s)", p->name);
    }
    else if (p->malloc_count != p->free_count) {
      SC_GLOBAL_LERRORF ("Memory balance (%s)\n", p->name);
    }
  }
}
예제 #2
0
static void
test_reduce (p4est_connectivity_t * conn, const char *which)
{
  SC_GLOBAL_INFOF ("Testing standard connectivity %s\n", which);
  SC_CHECK_ABORTF (p4est_connectivity_is_valid (conn),
                   "Invalid connectivity %s before reduce", which);
  p4est_connectivity_reduce (conn);
  SC_CHECK_ABORTF (p4est_connectivity_is_valid (conn),
                   "Invalid connectivity %s after reduce", which);
  SC_GLOBAL_INFOF ("Testing completion for reduced connectivity %s\n", which);
  p4est_connectivity_complete (conn);
  SC_CHECK_ABORTF (p4est_connectivity_is_valid (conn),
                   "Invalid connectivity %s after completion", which);
  p4est_connectivity_destroy (conn);
}
예제 #3
0
파일: sc.c 프로젝트: johannrudi/libsc
void               *
sc_calloc (int package, size_t nmemb, size_t size)
{
  void               *ret;
  int                *malloc_count = sc_malloc_count (package);

  /* allocate memory */
#if defined SC_ENABLE_MEMALIGN
  ret = sc_malloc_aligned (SC_MEMALIGN_BYTES, nmemb * size);
  memset (ret, 0, nmemb * size);
#else
  ret = calloc (nmemb, size);
  if (nmemb * size > 0) {
    SC_CHECK_ABORTF (ret != NULL, "Allocation (calloc size %lli)",
                     (long long int) size);
  }
#endif

  /* count the allocations */
#ifdef SC_ENABLE_PTHREAD
  sc_package_lock (package);
#endif
  if (nmemb * size > 0) {
    ++*malloc_count;
  }
  else {
    *malloc_count += ((ret == NULL) ? 0 : 1);
  }
#ifdef SC_ENABLE_PTHREAD
  sc_package_unlock (package);
#endif

  return ret;
}
예제 #4
0
파일: sc.c 프로젝트: johannrudi/libsc
void
sc_package_unregister (int package_id)
{
#ifdef SC_ENABLE_PTHREAD
  int                 i;
#endif
  sc_package_t       *p;

  SC_CHECK_ABORT (sc_package_is_registered (package_id),
                  "Package not registered");
  sc_memory_check (package_id);

  p = sc_packages + package_id;
  p->is_registered = 0;
  p->log_handler = NULL;
  p->log_threshold = SC_LP_DEFAULT;
  p->malloc_count = p->free_count = 0;
  p->rc_active = 0;
#ifdef SC_ENABLE_PTHREAD
  i = pthread_mutex_destroy (&p->mutex);
  SC_CHECK_ABORTF (i == 0, "Mutex destroy failed for package %s", p->name);
#endif
  p->name = p->full = NULL;

  --sc_num_packages;
}
예제 #5
0
static void
test_complete (p4est_connectivity_t * conn, const char *which, int test_p4est)
{
  SC_GLOBAL_INFOF ("Testing standard connectivity %s\n", which);
  SC_CHECK_ABORTF (p4est_connectivity_is_valid (conn),
                   "Invalid connectivity %s before completion", which);
  if (0 && test_p4est) {
    test_the_p4est (conn, 3);
  }

  SC_GLOBAL_INFOF ("Testing completion for connectivity %s\n", which);
  p4est_connectivity_complete (conn);
  SC_CHECK_ABORTF (p4est_connectivity_is_valid (conn),
                   "Invalid connectivity %s after completion", which);
  if (test_p4est) {
    test_the_p4est (conn, 3);
  }

  p4est_connectivity_destroy (conn);
}
예제 #6
0
파일: sc.c 프로젝트: aseyboldt/libsc
void
sc_memory_check (int package)
{
  sc_package_t       *p;

  if (package == -1)
    SC_CHECK_ABORT (default_malloc_count == default_free_count,
                    "Memory balance (default)");
  else {
    SC_ASSERT (sc_package_is_registered (package));
    p = sc_packages + package;
    SC_CHECK_ABORTF (p->malloc_count == p->free_count,
                     "Memory balance (%s)", p->name);
  }
}
예제 #7
0
파일: sc.c 프로젝트: aseyboldt/libsc
int
sc_package_register (sc_log_handler_t log_handler, int log_threshold,
                     const char *name, const char *full)
{
  int                 i;
  sc_package_t       *p;

  SC_CHECK_ABORT (sc_num_packages < SC_MAX_PACKAGES, "Too many packages");
  SC_CHECK_ABORT (log_threshold == SC_LP_DEFAULT ||
                  (log_threshold >= SC_LP_ALWAYS
                   && log_threshold <= SC_LP_SILENT),
                  "Invalid package log threshold");
  SC_CHECK_ABORT (strcmp (name, "default"), "Package default forbidden");
  SC_CHECK_ABORT (strchr (name, ' ') == NULL,
                  "Packages name contains spaces");

  /* sc_packages is static and thus initialized to all zeros */
  for (i = 0; i < SC_MAX_PACKAGES; ++i) {
    p = sc_packages + i;
    SC_CHECK_ABORTF (!p->is_registered || strcmp (p->name, name),
                     "Package %s is already registered", name);
  }
  for (i = 0; i < SC_MAX_PACKAGES; ++i) {
    p = sc_packages + i;
    if (!p->is_registered) {
      p->is_registered = 1;
      p->log_handler = log_handler;
      p->log_threshold = log_threshold;
      p->malloc_count = p->free_count = 0;
      p->name = name;
      p->full = full;
      break;
    }
  }
  SC_ASSERT (i < SC_MAX_PACKAGES);

  ++sc_num_packages;
  SC_ASSERT (sc_num_packages <= SC_MAX_PACKAGES);

  return i;
}
예제 #8
0
파일: sc.c 프로젝트: johannrudi/libsc
void               *
sc_realloc (int package, void *ptr, size_t size)
{
  if (ptr == NULL) {
    return sc_malloc (package, size);
  }
  else if (size == 0) {
    sc_free (package, ptr);
    return NULL;
  }
  else {
    void               *ret;

#if defined SC_ENABLE_MEMALIGN
    ret = sc_realloc_aligned (ptr, SC_MEMALIGN_BYTES, size);
#else
    ret = realloc (ptr, size);
    SC_CHECK_ABORTF (ret != NULL, "Reallocation (realloc size %lli)",
                     (long long int) size);
#endif

    return ret;
  }
}
예제 #9
0
int
main (int argc, char **argv)
{
  int                 mpiret;
  int                 mpirank, mpisize;
  int                 i, j;
  char                cvalue, cresult;
  int                 ivalue, iresult;
  unsigned short      usvalue, usresult;
  long                lvalue, lresult;
  float               fvalue[3], fresult[3], fexpect[3];
  double              dvalue, dresult;
  MPI_Comm            mpicomm;

  mpiret = MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);

  mpicomm = MPI_COMM_WORLD;
  mpiret = MPI_Comm_size (mpicomm, &mpisize);
  SC_CHECK_MPI (mpiret);
  mpiret = MPI_Comm_rank (mpicomm, &mpirank);
  SC_CHECK_MPI (mpiret);

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

  /* test allreduce int max */
  ivalue = mpirank;
  sc_allreduce (&ivalue, &iresult, 1, MPI_INT, MPI_MAX, mpicomm);
  SC_CHECK_ABORT (iresult == mpisize - 1, "Allreduce mismatch");

  /* test reduce float max */
  fvalue[0] = (float) mpirank;
  fexpect[0] = (float) (mpisize - 1);
  fvalue[1] = (float) (mpirank % 9 - 4);
  fexpect[1] = (float) (mpisize >= 9 ? 4 : (mpisize - 1) % 9 - 4);
  fvalue[2] = (float) (mpirank % 6);
  fexpect[2] = (float) (mpisize >= 6 ? 5 : (mpisize - 1) % 6);
  for (i = 0; i < mpisize; ++i) {
    sc_reduce (fvalue, fresult, 3, MPI_FLOAT, MPI_MAX, i, mpicomm);
    if (i == mpirank) {
      for (j = 0; j < 3; ++j) {
        SC_CHECK_ABORTF (fresult[j] == fexpect[j],      /* ok */
                         "Reduce mismatch in %d", j);
      }
    }
  }

  /* test allreduce char min */
  cvalue = (char) (mpirank % 127);
  sc_allreduce (&cvalue, &cresult, 1, MPI_CHAR, MPI_MIN, mpicomm);
  SC_CHECK_ABORT (cresult == 0, "Allreduce mismatch");

  /* test reduce unsigned short min */
  usvalue = (unsigned short) (mpirank % 32767);
  for (i = 0; i < mpisize; ++i) {
    sc_reduce (&usvalue, &usresult, 1, MPI_UNSIGNED_SHORT, MPI_MIN, i,
               mpicomm);
    if (i == mpirank) {
      SC_CHECK_ABORT (usresult == 0, "Reduce mismatch");
    }
  }

  /* test allreduce long sum */
  lvalue = (long) mpirank;
  sc_allreduce (&lvalue, &lresult, 1, MPI_LONG, MPI_SUM, mpicomm);
  SC_CHECK_ABORT (lresult == ((long) (mpisize - 1)) * mpisize / 2,
                  "Allreduce mismatch");

  /* test reduce double sum */
  dvalue = (double) mpirank;
  for (i = 0; i < mpisize; ++i) {
    sc_reduce (&dvalue, &dresult, 1, MPI_DOUBLE, MPI_SUM, i, mpicomm);
    if (i == mpirank) {
      SC_CHECK_ABORT (dresult == ((double) (mpisize - 1)) * mpisize / 2.,       /* ok */
                      "Reduce mismatch");
    }
  }

  sc_finalize ();

  mpiret = MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
예제 #10
0
파일: sc.c 프로젝트: johannrudi/libsc
static void        *
sc_malloc_aligned (size_t alignment, size_t size)
{
  /* minimum requirements on alignment */
  SC_ASSERT (sizeof (char **) == sizeof (void *));
  SC_ASSERT (sizeof (char **) >= sizeof (size_t));
  SC_ASSERT (alignment > 0 && alignment % sizeof (void *) == 0);
  SC_ASSERT (alignment == SC_MEMALIGN_BYTES);

#if defined SC_HAVE_ANY_MEMALIGN && defined SC_HAVE_POSIX_MEMALIGN
  {
    void               *data = NULL;
    int                 err = posix_memalign (&data, alignment, size);
    SC_CHECK_ABORTF (err != ENOMEM, "Insufficient memory (malloc size %llu)",
                     (long long unsigned) size);
    SC_CHECK_ABORTF (err != EINVAL, "Alignment %llu is not a power of two"
                     "or not a multiple of sizeof (void *)",
                     (long long unsigned) alignment);
    SC_CHECK_ABORTF (err == 0, "Return of %d from posix_memalign", err);
    return data;
  }
#elif defined SC_HAVE_ANY_MEMALIGN && defined SC_HAVE_ALIGNED_ALLOC
  {
    void               *data = aligned_alloc (alignment, size);
    SC_CHECK_ABORT (data != NULL || size == 0,
                    "Returned NULL from aligned_alloc");
    return data;
  }
#else
  {
#if 0
    /* adapted from PetscMallocAlign */
    int                *datastart = malloc (size + 2 * alignment);
    int                 shift = ((uintptr_t) datastart) % alignment;

    shift = (2 * alignment - shift) / sizeof (int);
    datastart[shift - 1] = shift;
    datastart += shift;
    return (void *) datastart;
#endif
    /* We pad to achieve alignment, then write the original pointer and data
     * size up front, then the real data shifted by at most alignment - 1
     * bytes.  This way there is always at least one stop byte at the end that
     * we can use for debugging. */
    const ptrdiff_t     extrasize = (const ptrdiff_t) (2 * sizeof (char **));
    const ptrdiff_t     signalign = (const ptrdiff_t) alignment;
    const size_t        alloc_size = extrasize + size + alignment;
    char               *alloc_ptr = (char *) malloc (alloc_size);
    char               *ptr;
    ptrdiff_t           shift, modu;

    SC_CHECK_ABORT (alloc_ptr != NULL, "Returned NULL from malloc");

    /* compute shift to the right where we put the actual data */
    modu = ((ptrdiff_t) alloc_ptr + extrasize) % signalign;
    shift = (signalign - modu) % signalign;
    SC_ASSERT (0 <= shift && shift < signalign);

    /* make sure the resulting pointer is fine */
    ptr = alloc_ptr + (extrasize + shift);
    SC_ASSERT ((ptrdiff_t) ptr % signalign == 0);

    /* memorize the original pointer that we got from malloc and fill up */
    SC_ARG_ALIGN (ptr, char *, SC_MEMALIGN_BYTES);

    /* remember parameters of allocation for later use */
    ((char **) ptr)[-1] = alloc_ptr;
    ((char **) ptr)[-2] = (char *) size;
#ifdef SC_ENABLE_DEBUG
    memset (alloc_ptr, -2, shift);
    SC_ASSERT (ptr + ((ptrdiff_t) size + signalign - shift) ==
               alloc_ptr + alloc_size);
    memset (ptr + size, -2, signalign - shift);
#endif

    /* and we are done */
    return (void *) ptr;
  }
#endif
}
예제 #11
0
파일: sc.c 프로젝트: johannrudi/libsc
int
sc_package_register (sc_log_handler_t log_handler, int log_threshold,
                     const char *name, const char *full)
{
  int                 i;
  sc_package_t       *p;
  sc_package_t       *new_package = NULL;
  int                 new_package_id = -1;

  SC_CHECK_ABORT (log_threshold == SC_LP_DEFAULT ||
                  (log_threshold >= SC_LP_ALWAYS &&
                   log_threshold <= SC_LP_SILENT),
                  "Invalid package log threshold");
  SC_CHECK_ABORT (strcmp (name, "default"), "Package default forbidden");
  SC_CHECK_ABORT (strchr (name, ' ') == NULL,
                  "Packages name contains spaces");

  /* sc_packages is static and thus initialized to all zeros */
  for (i = 0; i < sc_num_packages_alloc; ++i) {
    p = sc_packages + i;
    SC_CHECK_ABORTF (!p->is_registered || strcmp (p->name, name),
                     "Package %s is already registered", name);
  }

  /* Try to find unused space in sc_packages  */
  for (i = 0; i < sc_num_packages_alloc; ++i) {
    p = sc_packages + i;
    if (!p->is_registered) {
      new_package = p;
      new_package_id = i;
      break;
    }
  }

  /* realloc if the space in sc_packages is used up */
  if (i == sc_num_packages_alloc) {
    sc_packages = (sc_package_t *) realloc (sc_packages,
                                            (2 * sc_num_packages_alloc +
                                             1) * sizeof (sc_package_t));
    SC_CHECK_ABORT (sc_packages, "Failed to allocate memory");
    new_package = sc_packages + i;
    new_package_id = i;
    sc_num_packages_alloc = 2 * sc_num_packages_alloc + 1;

    /* initialize new packages */
    for (; i < sc_num_packages_alloc; i++) {
      p = sc_packages + i;
      p->is_registered = 0;
      p->log_handler = NULL;
      p->log_threshold = SC_LP_SILENT;
      p->log_indent = 0;
      p->malloc_count = 0;
      p->free_count = 0;
      p->rc_active = 0;
      p->name = NULL;
      p->full = NULL;
    }
  }

  new_package->is_registered = 1;
  new_package->log_handler = log_handler;
  new_package->log_threshold = log_threshold;
  new_package->log_indent = 0;
  new_package->malloc_count = 0;
  new_package->free_count = 0;
  new_package->rc_active = 0;
  new_package->abort_mismatch = 1;
  new_package->name = name;
  new_package->full = full;
#ifdef SC_ENABLE_PTHREAD
  i = pthread_mutex_init (&new_package->mutex, NULL);
  SC_CHECK_ABORTF (i == 0, "Mutex init failed for package %s", name);
#endif

  ++sc_num_packages;
  SC_ASSERT (sc_num_packages <= sc_num_packages_alloc);
  SC_ASSERT (0 <= new_package_id && new_package_id < sc_num_packages);

  return new_package_id;
}
예제 #12
0
static void
test_periodic (p8est_connectivity_t * conn)
{
  int                 i;
  int                 iface, nface;
  int                 iedge, icorner;
  int                 ft[9];
  size_t              zz;
  p4est_topidx_t      itree, ntree;
  p8est_edge_info_t   ei;
  p8est_edge_transform_t *et;
  p8est_corner_info_t ci;
  p8est_corner_transform_t *ct;
  sc_array_t         *eta, *cta;

  itree = 0;
  for (iface = 0; iface < 6; ++iface) {
    ntree = p8est_find_face_transform (conn, itree, iface, ft);
    nface = p8est_face_dual[iface];
    SC_CHECK_ABORT (ntree == itree, "PF tree");
    for (i = 0; i < 3; ++i) {
      SC_CHECK_ABORTF (ft[i] == ft[i + 3], "PF axis %d", i);
    }
    SC_CHECK_ABORT (ft[6] == 0 && ft[7] == 0, "PF reverse");
    SC_CHECK_ABORT (ft[8] == 2 * (iface % 2) + nface % 2, "PF code");
  }

  eta = &ei.edge_transforms;
  sc_array_init (eta, sizeof (p8est_edge_transform_t));
  for (iedge = 0; iedge < 12; ++iedge) {
    p8est_find_edge_transform (conn, itree, iedge, &ei);
    SC_CHECK_ABORT ((int) ei.iedge == iedge, "PE ei");
    SC_CHECK_ABORT (eta->elem_count == 1, "PE count");
    for (zz = 0; zz < eta->elem_count; ++zz) {
      et = p8est_edge_array_index (eta, zz);
      SC_CHECK_ABORT (et->ntree == itree, "PE tree");
      SC_CHECK_ABORT ((int) et->nedge + iedge == 8 * (iedge / 4) + 3,
                      "PE edge");
      SC_CHECK_ABORT (et->nflip == 0, "PE flip");
      SC_CHECK_ABORT (et->corners == et->nedge % 4, "PE corners");
      SC_CHECK_ABORT ((int) et->naxis[0] == iedge / 4 &&
                      et->naxis[1] < et->naxis[2] &&
                      et->naxis[0] + et->naxis[1] + et->naxis[2] == 3,
                      "PE axis");
    }
  }
  sc_array_reset (eta);

  cta = &ci.corner_transforms;
  sc_array_init (cta, sizeof (p8est_corner_transform_t));
  for (icorner = 0; icorner < 8; ++icorner) {
    p8est_find_corner_transform (conn, itree, icorner, &ci);
    SC_CHECK_ABORT ((int) ci.icorner == icorner, "PC ci");
    SC_CHECK_ABORT (cta->elem_count == 1, "PC count");
    for (zz = 0; zz < cta->elem_count; ++zz) {
      ct = p8est_corner_array_index (cta, zz);
      SC_CHECK_ABORT (ct->ntree == itree, "PC tree");
      SC_CHECK_ABORT (ct->ncorner + icorner == 7, "PC corner");
    }
  }
  sc_array_reset (cta);
}
예제 #13
0
static void
test_rotwrap (p8est_connectivity_t * conn)
{
  int                 i;
  int                 iface, nface;
  int                 iedge, icorner;
  int                 ft[9];
  size_t              zz;
  p4est_topidx_t      itree, ntree;
  p8est_edge_info_t   ei;
  p8est_edge_transform_t *et;
  p8est_corner_info_t ci;
  p8est_corner_transform_t *ct;
  sc_array_t         *eta, *cta;

  itree = 0;
  for (iface = 0; iface < 6; ++iface) {
    ntree = p8est_find_face_transform (conn, itree, iface, ft);
    if (iface == 2 || iface == 3) {
      SC_CHECK_ABORT (ntree == -1, "RF tree");
      continue;
    }
    nface = p8est_face_dual[iface];
    SC_CHECK_ABORT (ntree == itree, "RF tree");
    if (iface == 0 || iface == 1) {
      for (i = 0; i < 3; ++i) {
        SC_CHECK_ABORTF (ft[i] == (i + 1) % 3, "RFA axis A%d", i);
        SC_CHECK_ABORTF (ft[i] == ft[i + 3], "RFA axis B%d", i);
      }
      SC_CHECK_ABORT (ft[6] == 0 && ft[7] == 0, "RFA reverse");
    }
    else {
      for (i = 0; i < 3; ++i) {
        SC_CHECK_ABORTF (ft[i] == i, "RFB axis A%d", i);
      }
      SC_CHECK_ABORT (ft[0] == ft[4], "RFB axis B0");
      SC_CHECK_ABORT (ft[1] == ft[3], "RFB axis B1");
      SC_CHECK_ABORT (ft[2] == ft[5], "RFB axis B2");
      SC_CHECK_ABORT (ft[6] == (iface != 4) &&
                      ft[7] == (iface != 5), "RFB reverse");
    }
    SC_CHECK_ABORT (ft[8] == 2 * (iface % 2) + nface % 2, "RF code");
  }

  eta = &ei.edge_transforms;
  sc_array_init (eta, sizeof (p8est_edge_transform_t));
  for (iedge = 0; iedge < 12; ++iedge) {
    p8est_find_edge_transform (conn, itree, iedge, &ei);
    SC_CHECK_ABORT ((int) ei.iedge == iedge, "RE ei");
    SC_CHECK_ABORT ((int) eta->elem_count == 2 - (iedge / 4), "RE count AB");
    for (zz = 0; zz < eta->elem_count; ++zz) {
      et = p8est_edge_array_index (eta, zz);
      SC_CHECK_ABORT (et->ntree == itree, "RE tree");
      SC_CHECK_ABORT ((int) et->nedge == rotwrap_edges[iedge][zz], "RE edge");
      SC_CHECK_ABORT ((int) et->nflip == rotwrap_flip[iedge][zz], "RE flip");
      SC_CHECK_ABORT (et->corners == et->nedge % 4, "RE corners");
      SC_CHECK_ABORT ((int) et->naxis[0] == rotwrap_axes[iedge][zz] &&
                      et->naxis[1] < et->naxis[2] &&
                      et->naxis[0] + et->naxis[1] + et->naxis[2] == 3,
                      "RE axis");
    }
  }
  sc_array_reset (eta);

  cta = &ci.corner_transforms;
  sc_array_init (cta, sizeof (p8est_corner_transform_t));
  for (icorner = 0; icorner < 8; ++icorner) {
    p8est_find_corner_transform (conn, itree, icorner, &ci);
    SC_CHECK_ABORT ((int) ci.icorner == icorner, "RC ci");
    SC_CHECK_ABORT (cta->elem_count == 2, "RC count");
    for (zz = 0; zz < cta->elem_count; ++zz) {
      ct = p8est_corner_array_index (cta, zz);
      SC_CHECK_ABORT (ct->ntree == itree, "RC tree");
      SC_CHECK_ABORT ((int) ct->ncorner == rotwrap_corners[icorner][zz],
                      "RC corner");
    }
  }
  sc_array_reset (cta);
}
예제 #14
0
파일: mesh2.c 프로젝트: 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
    }
  }
}
예제 #15
0
static void
test_tree (p8est_geometry_t * geom, p4est_topidx_t which_tree,
           const double bounds[6], int N)
{
    const double        epsilon = 1e-8;
    int                 i, j, k, l, m;
    double              h[3];
    double              xyz[4][3], XYZ[4][3];
    double              Jgeom[3][3], Jdisc[3][3];
    double              detD, detJ, fd, fg;
    double              diffD, diffJ, maxJ;

    for (l = 0; l < 3; ++l) {
        h[l] = bounds[2 * l + 1] - bounds[2 * l];
    }

    for (i = 0; i < N; ++i) {
        xyz[3][2] = ((N - (i + .5)) * bounds[4] + (i + .5) * bounds[5]) / N;
        for (j = 0; j < N; ++j) {
            xyz[3][1] = ((N - (j + .5)) * bounds[2] + (j + .5) * bounds[3]) / N;
            for (k = 0; k < N; ++k) {
                xyz[3][0] = ((N - (k + .5)) * bounds[0] + (k + .5) * bounds[1]) / N;

                /* compute transformed point */
                geom->X (geom, which_tree, xyz[3], XYZ[3]);

                /* offset point three times in the coordinate directions */
                for (l = 0; l < 3; ++l) {       /* l runs in domain */
                    memcpy (xyz[l], xyz[3], 3 * sizeof (double));
                    xyz[l][l] += epsilon * h[l];
                    geom->X (geom, which_tree, xyz[l], XYZ[l]);

                    for (m = 0; m < 3; ++m) {     /* m runs in image domain */
                        Jdisc[m][l] = (XYZ[l][m] - XYZ[3][m]) / (epsilon * h[l]);
                    }
                }
                detJ = geom->J (geom, which_tree, xyz[3], Jgeom);
                detD = geom->D (geom, which_tree, xyz[3]);

                /* compare results */
                diffD = fabs (detD - detJ) / SC_MAX (detD, detJ);
                SC_CHECK_ABORTF (diffD < 1e-8, "Determinant mismatch %lld %g %g %g",
                                 (long long) which_tree, xyz[3][0], xyz[3][1],
                                 xyz[3][2]);

                diffJ = maxJ = 0.;
                for (l = 0; l < 3; ++l) {
                    for (m = 0; m < 3; ++m) {
                        fd = fabs (Jdisc[m][l]);
                        fg = fabs (Jgeom[m][l]);
                        maxJ = SC_MAX (maxJ, fd);
                        maxJ = SC_MAX (maxJ, fg);
                        diffJ += fabs (Jdisc[m][l] - Jgeom[m][l]);
                    }
                }
                diffJ /= 3 * 3 * maxJ;
                SC_CHECK_ABORTF (diffJ < 100. * epsilon,
                                 "Jacobian mismatch %lld %g %g %g",
                                 (long long) which_tree, xyz[3][0], xyz[3][1],
                                 xyz[3][2]);
            }
        }
    }
}
예제 #16
0
int
main (int argc, char **argv)
{
  int                 mpiret, retval;
  int                 mpirank;
  const char         *argbasename;
  char                afilename[BUFSIZ];
  p4est_topidx_t      tnum_flips;
  p8est_tets_t       *ptg;
  p8est_connectivity_t *connectivity;
  p8est_t            *p8est;
  MPI_Comm            mpicomm;

  mpiret = MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);
  mpicomm = MPI_COMM_WORLD;
  mpiret = MPI_Comm_rank (mpicomm, &mpirank);

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

  if (argc != 2) {
    SC_GLOBAL_LERRORF ("Usage: %s <tetgen file base name>\n", argv[0]);
    sc_abort ();
  }
  argbasename = argv[1];

  /* read tetgen nodes and tetrahedra from files */
  ptg = p8est_tets_read (argbasename);
  SC_CHECK_ABORTF (ptg != NULL, "Failed to read tetgen %s", argbasename);
  P4EST_GLOBAL_STATISTICSF ("Read %d nodes and %d tets %s attributes\n",
                            (int) ptg->nodes->elem_count / 3,
                            (int) ptg->tets->elem_count / 4,
                            ptg->tet_attributes != NULL ? "with" : "without");

  /* flip orientation to right-handed */
  tnum_flips = p8est_tets_make_righthanded (ptg);
  P4EST_GLOBAL_STATISTICSF ("Performed %ld orientation flip(s)\n",
                            (long) tnum_flips);

  /* create a connectivity from the tet mesh and save it */
  connectivity = p8est_connectivity_new_tets (ptg);
  if (mpirank == 0) {
    snprintf (afilename, BUFSIZ, "%s", "read_tetgen.p8c");
    retval = p8est_connectivity_save (afilename, connectivity);
    SC_CHECK_ABORT (retval == 0, "Failed connectivity_save");
  }

  /* create a forest and visualize */
  p8est = p8est_new (mpicomm, connectivity, 0, NULL, NULL);
  snprintf (afilename, BUFSIZ, "%s", "read_tetgen");
  p8est_vtk_write_file (p8est, NULL, afilename);

  /* clean up */
  p8est_destroy (p8est);
  p8est_connectivity_destroy (connectivity);
  p8est_tets_destroy (ptg);

  sc_finalize ();
  mpiret = MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}