static void p4est_coarsen_both (p4est_t * p4est, int coarsen_recursive, p4est_coarsen_t coarsen_fn, p4est_init_t init_fn) { int success; p4est_t *copy; copy = p4est_copy (p4est, 1); p4est_coarsen_old (copy, coarsen_recursive, coarsen_fn, init_fn); coarsen_callback_count = 0; p4est_coarsen_ext (p4est, coarsen_recursive, 1, coarsen_fn, init_fn, NULL); SC_CHECK_ABORT (coarsen_recursive || coarsen_callback_count == (int) p4est->local_num_quadrants, "Coarsen count"); success = p4est_is_equal (p4est, copy, 1); SC_CHECK_ABORT (success, "Coarsen mismatch"); p4est_destroy (copy); }
static void test_deflate (p4est_t * p4est) { p4est_gloidx_t *pertree; p4est_t *p4est2; sc_array_t *qarr, *darr; pertree = P4EST_ALLOC (p4est_gloidx_t, p4est->connectivity->num_trees + 1); p4est_comm_count_pertree (p4est, pertree); darr = NULL; qarr = p4est_deflate_quadrants (p4est, p4est->data_size > 0 ? &darr : NULL); /* Data that describes the forest completely (a) shared data (identical on all processors): p4est->connectivity p4est->global_first_quadrant (does not need to be stored away) pertree (b) per-processor data (partition independent after allgatherv): qarr darr (if per-quadrant data size is greater 0 and it should be saved) */ /* Create a forest from this information and compare */ p4est2 = p4est_inflate (p4est->mpicomm, p4est->connectivity, p4est->global_first_quadrant, pertree, qarr, darr, p4est->user_pointer); SC_CHECK_ABORT (p4est_is_equal (p4est, p4est2, 1), "de/inflate"); p4est_destroy (p4est2); /* clean up allocated memory */ P4EST_FREE (pertree); sc_array_destroy (qarr); if (darr != NULL) { sc_array_destroy (darr); } }
static void test_build_local (sc_MPI_Comm mpicomm) { sc_array_t *points; p4est_connectivity_t *conn; p4est_t *p4est, *built, *copy; test_build_t stb, *tb = &stb; /* 0. prepare data that we will reuse */ tb->maxlevel = 7 - P4EST_DIM; tb->counter = -1; tb->wrapper = 3; tb->init_default = -1; tb->init_add = -1; tb->count_add = -1; tb->last_tree = -1; tb->build = NULL; #ifndef P4_TO_P8 conn = p4est_connectivity_new_moebius (); #else conn = p8est_connectivity_new_rotcubes (); #endif /* P4_TO_P8 */ p4est = p4est_new_ext (mpicomm, conn, 0, 0, 2, 0, NULL, tb); p4est_refine (p4est, 1, test_build_refine, NULL); p4est_partition (p4est, 0, NULL); /* TODO: enrich tests with quadrant data */ /* 1. Create a p4est that shall be identical to the old one. */ tb->build = p4est_build_new (p4est, 0, NULL, NULL); p4est_search_local (p4est, 0, test_search_local_1, NULL, NULL); built = p4est_build_complete (tb->build); SC_CHECK_ABORT (p4est_is_equal (p4est, built, 0), "Mismatch build_local 1"); p4est_destroy (built); /* 2. Create a p4est that is as coarse as possible. * Coarsen recursively, compare. */ tb->build = p4est_build_new (p4est, 4, NULL, NULL); p4est_search_local (p4est, 0, test_search_local_2, NULL, NULL); built = p4est_build_complete (tb->build); copy = p4est_copy (p4est, 0); p4est_coarsen (copy, 1, test_build_coarsen, NULL); SC_CHECK_ABORT (p4est_is_equal (copy, built, 0), "Mismatch build_local 2"); p4est_destroy (copy); p4est_destroy (built); /* 3. Create a p4est with some random pattern for demonstration */ tb->init_default = 0; tb->init_add = 0; tb->count_add = 0; tb->build = p4est_build_new (p4est, 0, test_search_init_3, tb); p4est_build_init_add (tb->build, test_search_init_add_3); p4est_search_local (p4est, 1, test_search_local_3, NULL, NULL); built = p4est_build_complete (tb->build); p4est_build_verify_3 (built); SC_CHECK_ABORT (p4est_is_valid (built), "Invalid build_local 3"); p4est_destroy (built); /* 4. Create a p4est from a search with one quadrant per tree */ tb->init_default = 0; tb->init_add = 0; tb->count_add = 0; tb->last_tree = -1; tb->build = p4est_build_new (p4est, sizeof (long), test_search_init_4, tb); p4est_build_init_add (tb->build, test_search_init_add_4); p4est_search_local (p4est, 0, test_search_local_4, NULL, NULL); built = p4est_build_complete (tb->build); p4est_build_verify_4 (built); SC_CHECK_ABORT (p4est_is_valid (built), "Invalid build_local 4"); p4est_destroy (built); /* 5. Create a p4est from a multiple-item search */ points = sc_array_new_size (sizeof (int8_t), 2); *(int8_t *) sc_array_index (points, 0) = 0; *(int8_t *) sc_array_index (points, 1) = 1; tb->wrapper = 5; tb->init_default = 0; tb->init_add = 0; tb->build = p4est_build_new (p4est, 0, NULL, tb); p4est_search_local (p4est, 0, NULL, test_search_point_5, points); built = p4est_build_complete (tb->build); #if 0 p4est_build_verify_5 (built); #endif SC_CHECK_ABORT (p4est_is_valid (built), "Invalid build_local 5"); p4est_destroy (built); sc_array_destroy (points); /* clean up */ p4est_destroy (p4est); p4est_connectivity_destroy (conn); }
static void test_loadsave (p4est_connectivity_t * connectivity, const char *prefix, sc_MPI_Comm mpicomm, int mpirank) { int mpiret, retval; unsigned csum, csum2; double elapsed, wtime; p4est_connectivity_t *conn2; p4est_t *p4est, *p4est2; sc_statinfo_t stats[STATS_COUNT]; char conn_name[BUFSIZ]; char p4est_name[BUFSIZ]; snprintf (conn_name, BUFSIZ, "%s.%s", prefix, P4EST_CONN_SUFFIX); snprintf (p4est_name, BUFSIZ, "%s.%s", prefix, P4EST_FOREST_SUFFIX); P4EST_GLOBAL_INFOF ("Using file names %s and %s\n", conn_name, p4est_name); p4est = p4est_new_ext (mpicomm, connectivity, 0, 0, 0, sizeof (int), init_fn, NULL); p4est_refine (p4est, 1, refine_fn, init_fn); test_deflate (p4est); /* save, synchronize, load connectivity and compare */ if (mpirank == 0) { retval = p4est_connectivity_save (conn_name, connectivity); SC_CHECK_ABORT (retval == 0, "connectivity_save failed"); } mpiret = sc_MPI_Barrier (mpicomm); SC_CHECK_MPI (mpiret); wtime = sc_MPI_Wtime (); conn2 = p4est_connectivity_load (conn_name, NULL); elapsed = sc_MPI_Wtime () - wtime; sc_stats_set1 (stats + STATS_CONN_LOAD, elapsed, "conn load"); SC_CHECK_ABORT (p4est_connectivity_is_equal (connectivity, conn2), "load/save connectivity mismatch A"); p4est_connectivity_destroy (conn2); /* save, synchronize, load p4est and compare */ wtime = sc_MPI_Wtime (); p4est_save (p4est_name, p4est, 1); elapsed = sc_MPI_Wtime () - wtime; sc_stats_set1 (stats + STATS_P4EST_SAVE1, elapsed, "p4est save 1"); wtime = sc_MPI_Wtime (); p4est2 = p4est_load (p4est_name, mpicomm, sizeof (int), 1, NULL, &conn2); elapsed = sc_MPI_Wtime () - wtime; sc_stats_set1 (stats + STATS_P4EST_LOAD1a, elapsed, "p4est load 1a"); SC_CHECK_ABORT (p4est_connectivity_is_equal (connectivity, conn2), "load/save connectivity mismatch Ba"); SC_CHECK_ABORT (p4est_is_equal (p4est, p4est2, 1), "load/save p4est mismatch Ba"); p4est_destroy (p4est2); p4est_connectivity_destroy (conn2); wtime = sc_MPI_Wtime (); p4est2 = p4est_load (p4est_name, mpicomm, 0, 0, NULL, &conn2); elapsed = sc_MPI_Wtime () - wtime; sc_stats_set1 (stats + STATS_P4EST_LOAD1b, elapsed, "p4est load 1b"); SC_CHECK_ABORT (p4est_connectivity_is_equal (connectivity, conn2), "load/save connectivity mismatch Bb"); SC_CHECK_ABORT (p4est_is_equal (p4est, p4est2, 0), "load/save p4est mismatch Bb"); test_deflate (p4est2); p4est_destroy (p4est2); p4est_connectivity_destroy (conn2); /* partition and balance */ p4est_partition (p4est, 0, NULL); p4est_balance (p4est, P4EST_CONNECT_FULL, init_fn); csum = p4est_checksum (p4est); sc_stats_set1 (stats + STATS_P4EST_ELEMS, (double) p4est->local_num_quadrants, "p4est elements"); /* save, synchronize, load p4est and compare */ wtime = sc_MPI_Wtime (); p4est_save (p4est_name, p4est, 0); elapsed = sc_MPI_Wtime () - wtime; sc_stats_set1 (stats + STATS_P4EST_SAVE2, elapsed, "p4est save 2"); wtime = sc_MPI_Wtime (); p4est2 = p4est_load (p4est_name, mpicomm, sizeof (int), 0, NULL, &conn2); elapsed = sc_MPI_Wtime () - wtime; sc_stats_set1 (stats + STATS_P4EST_LOAD2, elapsed, "p4est load 2"); SC_CHECK_ABORT (p4est_connectivity_is_equal (connectivity, conn2), "load/save connectivity mismatch C"); SC_CHECK_ABORT (p4est_is_equal (p4est, p4est2, 0), "load/save p4est mismatch C"); p4est_destroy (p4est2); p4est_connectivity_destroy (conn2); /* save, synchronize, load p4est and compare */ wtime = sc_MPI_Wtime (); p4est_save (p4est_name, p4est, 1); elapsed = sc_MPI_Wtime () - wtime; sc_stats_set1 (stats + STATS_P4EST_SAVE3, elapsed, "p4est save 3"); wtime = sc_MPI_Wtime (); p4est2 = p4est_load (p4est_name, mpicomm, sizeof (int), 0, NULL, &conn2); elapsed = sc_MPI_Wtime () - wtime; sc_stats_set1 (stats + STATS_P4EST_LOAD3, elapsed, "p4est load 3"); SC_CHECK_ABORT (p4est_connectivity_is_equal (connectivity, conn2), "load/save connectivity mismatch D"); SC_CHECK_ABORT (p4est_is_equal (p4est, p4est2, 0), "load/save p4est mismatch D"); p4est_destroy (p4est2); p4est_connectivity_destroy (conn2); /* Test autopartition load feature */ wtime = sc_MPI_Wtime (); p4est2 = p4est_load_ext (p4est_name, mpicomm, sizeof (int), 0, 1, 0, NULL, &conn2); elapsed = sc_MPI_Wtime () - wtime; csum2 = p4est_checksum (p4est2); sc_stats_set1 (stats + STATS_P4EST_LOAD4, elapsed, "p4est load 4"); SC_CHECK_ABORT (p4est_connectivity_is_equal (connectivity, conn2), "load/save connectivity mismatch E"); SC_CHECK_ABORT (mpirank != 0 || csum == csum2, "load/save p4est mismatch E"); p4est_destroy (p4est2); p4est_connectivity_destroy (conn2); /* destroy data structures */ p4est_destroy (p4est); /* compute and print timings */ sc_stats_compute (mpicomm, STATS_COUNT, stats); sc_stats_print (p4est_package_id, SC_LP_STATISTICS, STATS_COUNT, stats, 0, 1); }
static void test_partition_circle (sc_MPI_Comm mpicomm, p4est_connectivity_t * connectivity, p4est_gloidx_t * pertree1, p4est_gloidx_t * pertree2) { int i, j; int num_procs; int empty_proc1, empty_proc2; unsigned crc1, crc2; p4est_gloidx_t global_num; p4est_locidx_t *new_counts; p4est_t *p4est, *copy; /* Create a forest and make a copy */ circle_count = 0; p4est = p4est_new_ext (mpicomm, connectivity, 0, 3, 1, sizeof (int), circle_init, NULL); num_procs = p4est->mpisize; test_pertree (p4est, NULL, pertree1); global_num = p4est->global_num_quadrants; crc1 = p4est_checksum (p4est); copy = p4est_copy (p4est, 1); P4EST_ASSERT (p4est_checksum (copy) == crc1); new_counts = P4EST_ALLOC (p4est_locidx_t, num_procs); /* Partition with one empty processor */ if (num_procs > 1) { P4EST_GLOBAL_INFO ("First circle partition\n"); empty_proc1 = num_procs / 3; j = 0; for (i = 0; i < num_procs; ++i) { if (i == empty_proc1) { new_counts[i] = 0; } else { new_counts[i] = p4est_partition_cut_gloidx (global_num, j + 1, num_procs - 1) - p4est_partition_cut_gloidx (global_num, j, num_procs - 1); P4EST_ASSERT (new_counts[i] >= 0); ++j; } } P4EST_ASSERT (j == num_procs - 1); p4est_partition_given (p4est, new_counts); test_pertree (p4est, pertree1, pertree2); crc2 = p4est_checksum (p4est); SC_CHECK_ABORT (crc1 == crc2, "First checksum mismatch"); } /* Partition with two empty processors */ if (num_procs > 2) { P4EST_GLOBAL_INFO ("Second circle partition\n"); empty_proc1 = (2 * num_procs) / 3 - 2; empty_proc2 = (2 * num_procs) / 3; j = 0; for (i = 0; i < num_procs; ++i) { if (i == empty_proc1 || i == empty_proc2) { new_counts[i] = 0; } else { new_counts[i] = p4est_partition_cut_gloidx (global_num, j + 1, num_procs - 2) - p4est_partition_cut_gloidx (global_num, j, num_procs - 2); P4EST_ASSERT (new_counts[i] >= 0); ++j; } } P4EST_ASSERT (j == num_procs - 2); p4est_partition_given (p4est, new_counts); test_pertree (p4est, pertree1, pertree2); crc2 = p4est_checksum (p4est); SC_CHECK_ABORT (crc1 == crc2, "Second checksum mismatch"); } /* Uniform partition */ P4EST_GLOBAL_INFO ("Third circle partition\n"); p4est_partition (p4est, 0, NULL); test_pertree (p4est, pertree1, pertree2); crc2 = p4est_checksum (p4est); SC_CHECK_ABORT (crc1 == crc2, "Third checksum mismatch"); SC_CHECK_ABORT (p4est_is_equal (p4est, copy, 1), "Forest mismatch"); P4EST_FREE (new_counts); p4est_destroy (copy); p4est_destroy (p4est); }