diff --git a/benchmarks/time_forest_partition.cxx b/benchmarks/time_forest_partition.cxx index 3b62cf19d9..12d9230dcb 100644 --- a/benchmarks/time_forest_partition.cxx +++ b/benchmarks/time_forest_partition.cxx @@ -323,7 +323,7 @@ t8_time_forest_create_cmesh (const char *msh_file, int mesh_dim, const char *cme /* partition the cmesh uniformly */ t8_cmesh_init (&cmesh_partition); t8_cmesh_set_derive (cmesh_partition, cmesh); - t8_cmesh_set_partition_uniform (cmesh_partition, init_level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, init_level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_set_profiling (cmesh_partition, 1); t8_cmesh_commit (cmesh_partition, comm); return cmesh_partition; diff --git a/example/IO/cmesh/gmsh/t8_load_and_refine_square_w_hole.cxx b/example/IO/cmesh/gmsh/t8_load_and_refine_square_w_hole.cxx index ffe4caa3f4..ce09b5eea0 100644 --- a/example/IO/cmesh/gmsh/t8_load_and_refine_square_w_hole.cxx +++ b/example/IO/cmesh/gmsh/t8_load_and_refine_square_w_hole.cxx @@ -149,7 +149,7 @@ t8_load_refine_build_forest (t8_cmesh_t cmesh, sc_MPI_Comm comm, int level) t8_cmesh_t cmesh_partition; t8_cmesh_init (&cmesh_partition); - t8_cmesh_set_partition_uniform (cmesh_partition, level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_set_derive (cmesh_partition, cmesh); t8_cmesh_commit (cmesh_partition, comm); diff --git a/example/IO/cmesh/gmsh/t8_read_msh_file.cxx b/example/IO/cmesh/gmsh/t8_read_msh_file.cxx index 0678e9e3ed..36cfb1d675 100644 --- a/example/IO/cmesh/gmsh/t8_read_msh_file.cxx +++ b/example/IO/cmesh/gmsh/t8_read_msh_file.cxx @@ -59,7 +59,7 @@ t8_read_msh_partition (t8_cmesh_t cmesh, const char *prefix) t8_cmesh_init (&p_mesh); t8_cmesh_set_derive (p_mesh, cmesh); - t8_cmesh_set_partition_uniform (p_mesh, 0, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (p_mesh, 0, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (p_mesh, sc_MPI_COMM_WORLD); snprintf (vtk_prefix, BUFSIZ, "%s_partition", prefix); t8_read_msh_file_vtk (p_mesh, vtk_prefix); diff --git a/example/IO/cmesh/t8_cmesh_load_save.cxx b/example/IO/cmesh/t8_cmesh_load_save.cxx index 9a5e9ab0db..6b49126ed4 100644 --- a/example/IO/cmesh/t8_cmesh_load_save.cxx +++ b/example/IO/cmesh/t8_cmesh_load_save.cxx @@ -44,7 +44,7 @@ t8_cmesh_load_distribute (const char *fileprefix, int num_files, int no_vtk) } t8_cmesh_init (&cmesh_partition); t8_cmesh_set_derive (cmesh_partition, cmesh); - t8_cmesh_set_partition_uniform (cmesh_partition, 0, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, 0, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_partition, sc_MPI_COMM_WORLD); if (!no_vtk) { t8_cmesh_vtk_write_file (cmesh_partition, "cmesh_dist_loaded_partition"); @@ -67,7 +67,7 @@ t8_cmesh_save_cmesh (const char *mshfile, int dim) cmesh = t8_cmesh_from_msh_file (mshfile, 1, sc_MPI_COMM_WORLD, dim, 0, 0); t8_cmesh_init (&cmesh_partition); t8_cmesh_set_derive (cmesh_partition, cmesh); - t8_cmesh_set_partition_uniform (cmesh_partition, 0, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, 0, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_partition, sc_MPI_COMM_WORLD); cmesh = cmesh_partition; } diff --git a/example/IO/cmesh/triangle/t8_read_triangle_file.cxx b/example/IO/cmesh/triangle/t8_read_triangle_file.cxx index b5ba185158..3f7c808aa3 100644 --- a/example/IO/cmesh/triangle/t8_read_triangle_file.cxx +++ b/example/IO/cmesh/triangle/t8_read_triangle_file.cxx @@ -45,7 +45,7 @@ t8_read_triangle_file_build_cmesh (const char *prefix, int do_dup, int do_partit t8_cmesh_init (&cmesh_part); t8_cmesh_ref (cmesh); t8_cmesh_set_derive (cmesh_part, cmesh); - t8_cmesh_set_partition_uniform (cmesh_part, 1, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_part, 1, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_part, sc_MPI_COMM_WORLD); snprintf (fileprefix, BUFSIZ, "%s_t8_triangle_partition", prefix); if (!t8_cmesh_vtk_write_file (cmesh_part, fileprefix)) { diff --git a/example/IO/cmesh/vtk/t8_cmesh_read_from_vtk.cxx b/example/IO/cmesh/vtk/t8_cmesh_read_from_vtk.cxx index 392a7829b5..9da72ed0a7 100644 --- a/example/IO/cmesh/vtk/t8_cmesh_read_from_vtk.cxx +++ b/example/IO/cmesh/vtk/t8_cmesh_read_from_vtk.cxx @@ -55,7 +55,7 @@ t8_forest_construct_from_vtk (const char *prefix, sc_MPI_Comm comm, const int va if (partition) { t8_cmesh_init (&cmesh); t8_cmesh_set_derive (cmesh, cmesh_in); - t8_cmesh_set_partition_uniform (cmesh, 0, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh, 0, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh, comm); snprintf (out_file, BUFSIZ - 16, "%s_cmesh_partition", out_prefix); t8_cmesh_vtk_write_file (cmesh, out_file); diff --git a/example/IO/forest/netcdf/t8_write_forest_netcdf.cxx b/example/IO/forest/netcdf/t8_write_forest_netcdf.cxx index 476850ba38..2de98f0679 100644 --- a/example/IO/forest/netcdf/t8_write_forest_netcdf.cxx +++ b/example/IO/forest/netcdf/t8_write_forest_netcdf.cxx @@ -201,7 +201,7 @@ t8_example_compare_performance_netcdf_var_properties (sc_MPI_Comm comm, int fore cmesh = t8_cmesh_new_hypercube_hybrid (comm, 1, 0); /* Build a (partioined) uniform forest */ - forest = t8_forest_new_uniform (cmesh, default_scheme, forest_refinement_level, 0, comm); + forest = t8_forest_new_uniform (cmesh, default_scheme, forest_refinement_level, 0, 0, comm); /* If the adapt_forest flag is set, the forest will be adapted */ if (adapt_forest) { @@ -352,7 +352,7 @@ t8_example_netcdf_write_forest (sc_MPI_Comm comm, int forest_refinement_level, i t8_global_productionf ("New cmesh was created\n"); /* Build a (partioined) uniform forest */ - forest = t8_forest_new_uniform (cmesh, default_scheme, level, 0, comm); + forest = t8_forest_new_uniform (cmesh, default_scheme, level, 0, 0, comm); t8_global_productionf ("New forest was created\n"); diff --git a/example/advect/t8_advection.cxx b/example/advect/t8_advection.cxx index 26df9ee5c0..eacb1fadfd 100644 --- a/example/advect/t8_advection.cxx +++ b/example/advect/t8_advection.cxx @@ -850,7 +850,7 @@ t8_advect_create_cmesh (sc_MPI_Comm comm, int cube_type, const char *mshfile, in } /* partition this cmesh according to the initial refinement level */ t8_cmesh_init (&cmesh_partition); - t8_cmesh_set_partition_uniform (cmesh_partition, level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_set_derive (cmesh_partition, cmesh); t8_cmesh_commit (cmesh_partition, comm); return cmesh_partition; @@ -938,7 +938,7 @@ t8_advect_problem_init (t8_cmesh_t cmesh, t8_flow_function_3d_fn u, t8_example_l /* Construct uniform forest with ghosts */ default_scheme = t8_scheme_new_default_cxx (); - problem->forest = t8_forest_new_uniform (cmesh, default_scheme, level, 1, comm); + problem->forest = t8_forest_new_uniform (cmesh, default_scheme, level, 1, 0, comm); /* Initialize the element array with num_local_elements + num_ghosts entries. */ diff --git a/example/cmesh/t8_cmesh_geometry_examples.cxx b/example/cmesh/t8_cmesh_geometry_examples.cxx index c43f22d8ac..3862095c90 100644 --- a/example/cmesh/t8_cmesh_geometry_examples.cxx +++ b/example/cmesh/t8_cmesh_geometry_examples.cxx @@ -118,7 +118,7 @@ main (int argc, char **argv) t8_cmesh_t cmesh = t8_cmesh_new_quadrangulated_disk (radius, comm); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, comm); t8_cmesh_vtk_write_file (cmesh, prefix_cmesh); t8_global_productionf ("Wrote %s.\n", prefix_cmesh); @@ -138,7 +138,7 @@ main (int argc, char **argv) t8_cmesh_t cmesh = t8_cmesh_new_triangulated_spherical_surface_octahedron (radius, comm); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, comm); t8_cmesh_vtk_write_file (cmesh, prefix_cmesh); t8_global_productionf ("Wrote %s.\n", prefix_cmesh); @@ -158,7 +158,7 @@ main (int argc, char **argv) t8_cmesh_t cmesh = t8_cmesh_new_triangulated_spherical_surface_icosahedron (radius, comm); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, comm); t8_cmesh_vtk_write_file (cmesh, prefix_cmesh); t8_global_productionf ("Wrote %s.\n", prefix_cmesh); @@ -178,7 +178,7 @@ main (int argc, char **argv) t8_cmesh_t cmesh = t8_cmesh_new_quadrangulated_spherical_surface (radius, comm); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, comm); t8_cmesh_vtk_write_file (cmesh, prefix_cmesh); t8_global_productionf ("Wrote %s.\n", prefix_cmesh); @@ -203,7 +203,7 @@ main (int argc, char **argv) t8_cmesh_t cmesh = t8_cmesh_new_cubed_spherical_shell (inner_radius, shell_thickness, num_levels, num_layers, comm); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, comm); t8_cmesh_vtk_write_file (cmesh, prefix_cmesh); t8_global_productionf ("Wrote %s.\n", prefix_cmesh); @@ -227,7 +227,7 @@ main (int argc, char **argv) t8_cmesh_t cmesh = t8_cmesh_new_prismed_spherical_shell_octahedron (inner_radius, shell_thickness, num_levels, num_layers, comm); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, comm); t8_cmesh_vtk_write_file (cmesh, prefix_cmesh); t8_global_productionf ("Wrote %s.\n", prefix_cmesh); @@ -251,7 +251,7 @@ main (int argc, char **argv) t8_cmesh_t cmesh = t8_cmesh_new_prismed_spherical_shell_icosahedron (inner_radius, shell_thickness, num_levels, num_layers, comm); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, comm); t8_cmesh_vtk_write_file (cmesh, prefix_cmesh); t8_global_productionf ("Wrote %s.\n", prefix_cmesh); @@ -271,7 +271,7 @@ main (int argc, char **argv) t8_cmesh_t cmesh = t8_cmesh_new_cubed_sphere (radius, comm); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, comm); t8_cmesh_vtk_write_file (cmesh, prefix_cmesh); t8_global_productionf ("Wrote %s.\n", prefix_cmesh); diff --git a/example/cmesh/t8_cmesh_hypercube_pad.cxx b/example/cmesh/t8_cmesh_hypercube_pad.cxx index fd8c65373d..a60e2d016b 100644 --- a/example/cmesh/t8_cmesh_hypercube_pad.cxx +++ b/example/cmesh/t8_cmesh_hypercube_pad.cxx @@ -55,7 +55,7 @@ main (int argc, char **argv) t8_global_productionf (" [step1] Local number of trees:\t%i\n", local_num_trees); t8_global_productionf (" [step1] Global number of trees:\t%li\n", global_num_trees); t8_scheme_cxx *scheme = t8_scheme_new_default_cxx (); - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, 0, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, 0, 0, 0, sc_MPI_COMM_WORLD); t8_forest_vtk_write_file (forest, prefix, 1, 1, 1, 1, 0, 0, NULL); t8_forest_unref (&forest); diff --git a/example/cmesh/t8_cmesh_partition.cxx b/example/cmesh/t8_cmesh_partition.cxx index 8e992b0a61..e400f2e17b 100644 --- a/example/cmesh/t8_cmesh_partition.cxx +++ b/example/cmesh/t8_cmesh_partition.cxx @@ -107,7 +107,7 @@ t8_partition (int level, int partition_from) /* We still need access to cmesh later */ t8_cmesh_ref (cmesh); t8_cmesh_set_derive (cmesh_part, cmesh); - t8_cmesh_set_partition_uniform (cmesh_part, level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_part, level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_part, sc_MPI_COMM_WORLD); if (mpisize > 1 && 1) { t8_cmesh_init (&cmesh_part2); diff --git a/example/forest/t8_test_face_iterate.cxx b/example/forest/t8_test_face_iterate.cxx index 343d748bfb..135ef809da 100644 --- a/example/forest/t8_test_face_iterate.cxx +++ b/example/forest/t8_test_face_iterate.cxx @@ -116,7 +116,7 @@ t8_test_fiterate_refine_and_partition (t8_cmesh_t cmesh, int level, sc_MPI_Comm /* partition the initial cmesh according to a uniform forest */ t8_cmesh_init (&cmesh_partition); t8_cmesh_set_derive (cmesh_partition, cmesh); - t8_cmesh_set_partition_uniform (cmesh_partition, level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_partition, comm); } else { @@ -126,7 +126,7 @@ t8_test_fiterate_refine_and_partition (t8_cmesh_t cmesh, int level, sc_MPI_Comm if (!no_vtk) { t8_cmesh_vtk_write_file (cmesh_partition, "test_fiterate_cmesh1"); } - forest = t8_forest_new_uniform (cmesh_partition, t8_scheme_new_default_cxx (), level, 0, comm); + forest = t8_forest_new_uniform (cmesh_partition, t8_scheme_new_default_cxx (), level, 0, 0, comm); t8_test_fiterate (forest); t8_forest_init (&forest_adapt); diff --git a/example/forest/t8_test_ghost.cxx b/example/forest/t8_test_ghost.cxx index ddfb3c73e7..cdad2b6104 100644 --- a/example/forest/t8_test_ghost.cxx +++ b/example/forest/t8_test_ghost.cxx @@ -63,7 +63,7 @@ t8_adapt_every_third_element (t8_forest_t forest, t8_forest_t forest_from, t8_lo int level; T8_ASSERT (!is_family || num_elements == ts->t8_element_num_children (elements[0])); level = ts->t8_element_level (elements[0]); - if (ts->t8_element_get_linear_id (elements[0], level) % 3 == 0) { + if (ts->t8_element_get_linear_id (elements[0], level, 0) % 3 == 0) { return 1; } return 0; @@ -125,7 +125,7 @@ t8_test_ghost_refine_and_partition (t8_cmesh_t cmesh, const int level, sc_MPI_Co /* partition the initial cmesh according to a uniform forest */ t8_cmesh_init (&cmesh_partition); t8_cmesh_set_derive (cmesh_partition, cmesh); - t8_cmesh_set_partition_uniform (cmesh_partition, level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_partition, comm); } else { @@ -135,7 +135,7 @@ t8_test_ghost_refine_and_partition (t8_cmesh_t cmesh, const int level, sc_MPI_Co if (!no_vtk) { t8_cmesh_vtk_write_file (cmesh_partition, "test_ghost_cmesh1"); } - forest = t8_forest_new_uniform (cmesh_partition, t8_scheme_new_default_cxx (), level, 1, comm); + forest = t8_forest_new_uniform (cmesh_partition, t8_scheme_new_default_cxx (), level, 1, 0, comm); /* adapt (if desired), partition and create ghosts for the forest */ t8_forest_init (&forest_ghost); diff --git a/example/forest/t8_test_ghost_large_level_diff.cxx b/example/forest/t8_test_ghost_large_level_diff.cxx index 787dcb565c..648ce093d9 100644 --- a/example/forest/t8_test_ghost_large_level_diff.cxx +++ b/example/forest/t8_test_ghost_large_level_diff.cxx @@ -142,7 +142,7 @@ t8_ghost_large_level_diff (const char *prefix, int dim, int level, int refine, i } t8_cmesh_init (&cmesh_partition); t8_cmesh_set_derive (cmesh_partition, cmesh); - t8_cmesh_set_partition_uniform (cmesh_partition, level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_partition, comm); if (!no_vtk) { t8_cmesh_vtk_write_file (cmesh_partition, "partitioned_cmesh"); diff --git a/example/geometry/t8_example_geometries.cxx b/example/geometry/t8_example_geometries.cxx index b492276ef4..77edfcc063 100644 --- a/example/geometry/t8_example_geometries.cxx +++ b/example/geometry/t8_example_geometries.cxx @@ -1022,7 +1022,7 @@ t8_analytic_geom (int level, t8_example_geom_type geom_type) * 2 and refine recursively only along the boundary. */ uniform_level = geom_type == T8_GEOM_CIRCLE ? SC_MIN (2, level) : level; /* Create a uniform forest */ - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), uniform_level, 0, 0, sc_MPI_COMM_WORLD); if (geom_type == T8_GEOM_CIRCLE) { t8_forest_t forest_adapt; /* Create a forest that is only refined at the tree boundaries. diff --git a/example/remove/t8_example_empty_trees.cxx b/example/remove/t8_example_empty_trees.cxx index 9aac0dce47..4e46fe7c71 100644 --- a/example/remove/t8_example_empty_trees.cxx +++ b/example/remove/t8_example_empty_trees.cxx @@ -55,7 +55,7 @@ t8_strip_of_quads (t8_gloidx_t num_trees, t8_gloidx_t empty_tree, const char **v t8_cmesh_t cmesh = t8_cmesh_new_hypercube_pad (T8_ECLASS_QUAD, sc_MPI_COMM_WORLD, boundary_coords, num_trees, 1, 0, use_axis_alined); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 0, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 0, 0, 0, sc_MPI_COMM_WORLD); t8_forest_write_vtk (forest, *vtuname); t8_debugf ("Output to %s\n", *vtuname); diff --git a/example/remove/t8_example_gauss_blob.cxx b/example/remove/t8_example_gauss_blob.cxx index f8bf76480a..2a10a3b63a 100644 --- a/example/remove/t8_example_gauss_blob.cxx +++ b/example/remove/t8_example_gauss_blob.cxx @@ -151,7 +151,7 @@ t8_construct_spheres (const int initial_level, const double radius_inner, const * Its center is therefore the center of the corresponding surface. */ struct t8_adapt_data adapt_data = { remove_scope, radius_inner, radius_outer, { 0.5, 0.5, 0.5 } }; - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), initial_level, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), initial_level, 0, 0, sc_MPI_COMM_WORLD); forest = t8_forest_new_adapt (forest, t8_adapt_refine, 0, 0, &adapt_data); if (remove_scope > 0) { forest = t8_forest_new_adapt (forest, t8_adapt_remove, 0, 0, &adapt_data); diff --git a/example/remove/t8_example_spheres.cxx b/example/remove/t8_example_spheres.cxx index c610cc0e7c..2d4d57f8ed 100644 --- a/example/remove/t8_example_spheres.cxx +++ b/example/remove/t8_example_spheres.cxx @@ -110,7 +110,7 @@ t8_construct_spheres (const int initial_level, const double radius_inner, const = { 1.0, 0.5, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 1.0, 0.0, 0.5, 0.5, 0.5, 0.0, 0.5, 0.5, 0.5, 0.0 }; struct t8_adapt_data adapt_data = { num_spheres, radius_inner, radius_outer, midpoints }; - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), initial_level, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), initial_level, 0, 0, sc_MPI_COMM_WORLD); forest = t8_forest_new_adapt (forest, t8_adapt_callback_refine, 0, 0, &adapt_data); forest = t8_forest_new_adapt (forest, t8_adapt_callback_remove, 0, 0, &adapt_data); diff --git a/src/t8_cmesh.h b/src/t8_cmesh.h index 1d04afc84f..d577628c12 100644 --- a/src/t8_cmesh.h +++ b/src/t8_cmesh.h @@ -211,12 +211,13 @@ t8_cmesh_set_partition_offsets (t8_cmesh_t cmesh, t8_shmem_array_t tree_offsets) * to \ref t8_cmesh_commit. * \param [in,out] cmesh The cmesh to be updated. * \param [in] element_level The refinement_level. + * \param [in] multilevel Partition the cmesh for a multilevel forest. * \param [in] ts The element scheme describing the refinement pattern. * We take ownership. This can be prevented by * referencing \b ts before calling this function. */ void -t8_cmesh_set_partition_uniform (t8_cmesh_t cmesh, int element_level, t8_scheme_cxx_t *ts); +t8_cmesh_set_partition_uniform (t8_cmesh_t cmesh, int element_level, const int multilevel, t8_scheme_cxx_t *ts); /** Refine the cmesh to a given level. * Thus split each tree into x^level subtrees @@ -726,19 +727,20 @@ t8_cmesh_get_partition_table (t8_cmesh_t cmesh); * \param [in] cmesh The cmesh to be considered. * \param [in] level The uniform refinement level to be created. * \param [in] ts The element scheme for which to compute the bounds. + * \param [in] multilevel Flag if the ancestors will be saved as well. * \param [out] first_local_tree The first tree that contains elements belonging to the calling processor. - * \param [out] child_in_tree_begin The global index of the first element belonging to the calling processor. Not computed if NULL. + * \param [out] element_in_tree_begin The global index of the first element belonging to the calling processor. Not computed if NULL. * \param [out] last_local_tree The last tree that contains elements belonging to the calling processor. - * \param [out] child_in_tree_end The global index of the first element that does not belonging to + * \param [out] element_in_tree_end The global index of the first element that does not belonging to * the calling processor anymore. Not computed if NULL. * \param [out] first_tree_shared If not NULL, 1 or 0 is stored here depending on whether \a first_local_tree is the * same as \a last_local_tree on the next process. * \a cmesh must be committed before calling this function. * */ void -t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, int level, t8_scheme_cxx_t *ts, t8_gloidx_t *first_local_tree, - t8_gloidx_t *child_in_tree_begin, t8_gloidx_t *last_local_tree, t8_gloidx_t *child_in_tree_end, - int8_t *first_tree_shared); +t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, int level, t8_scheme_cxx_t *ts, const int multilevel, + t8_gloidx_t *first_local_tree, t8_gloidx_t *element_in_tree_begin, + t8_gloidx_t *last_local_tree, t8_gloidx_t *element_in_tree_end, int8_t *first_tree_shared); /** Increase the reference counter of a cmesh. * \param [in,out] cmesh On input, this cmesh must exist with positive diff --git a/src/t8_cmesh/t8_cmesh.cxx b/src/t8_cmesh/t8_cmesh.cxx index 98b5a95bd4..fa7d59f484 100644 --- a/src/t8_cmesh/t8_cmesh.cxx +++ b/src/t8_cmesh/t8_cmesh.cxx @@ -162,6 +162,7 @@ t8_cmesh_init (t8_cmesh_t *pcmesh) /* sensible (hard error) defaults */ cmesh->set_partition_level = -1; + cmesh->set_partition_multilevel = 0; cmesh->dimension = -1; /*< ok; force user to select dimension */ cmesh->mpirank = -1; cmesh->mpisize = -1; @@ -263,7 +264,7 @@ t8_cmesh_set_partition_offsets (t8_cmesh_t cmesh, t8_shmem_array_t tree_offsets) } void -t8_cmesh_set_partition_uniform (t8_cmesh_t cmesh, int element_level, t8_scheme_cxx_t *ts) +t8_cmesh_set_partition_uniform (t8_cmesh_t cmesh, const int element_level, const int multilevel, t8_scheme_cxx_t *ts) { T8_ASSERT (t8_cmesh_is_initialized (cmesh)); T8_ASSERT (element_level >= -1); @@ -271,6 +272,7 @@ t8_cmesh_set_partition_uniform (t8_cmesh_t cmesh, int element_level, t8_scheme_c cmesh->set_partition = 1; cmesh->set_partition_level = element_level; + cmesh->set_partition_multilevel = multilevel; cmesh->set_partition_scheme = ts; if (element_level >= 0) { /* We overwrite any previous partition settings */ diff --git a/src/t8_cmesh/t8_cmesh_copy.c b/src/t8_cmesh/t8_cmesh_copy.c index de5d0e7ea4..9475621c25 100644 --- a/src/t8_cmesh/t8_cmesh_copy.c +++ b/src/t8_cmesh/t8_cmesh_copy.c @@ -54,6 +54,7 @@ t8_cmesh_copy (t8_cmesh_t cmesh, t8_cmesh_t cmesh_from, sc_MPI_Comm comm) cmesh->num_trees = cmesh_from->num_trees; cmesh->set_partition = cmesh_from->set_partition; cmesh->set_partition_level = cmesh_from->set_partition_level; + cmesh->set_partition_multilevel = cmesh_from->set_partition_multilevel; T8_ASSERT (t8_cmesh_comm_is_valid (cmesh, comm)); /* Copy the tree_offsets */ diff --git a/src/t8_cmesh/t8_cmesh_cxx.cxx b/src/t8_cmesh/t8_cmesh_cxx.cxx index 16b770606c..7b2644255f 100644 --- a/src/t8_cmesh/t8_cmesh_cxx.cxx +++ b/src/t8_cmesh/t8_cmesh_cxx.cxx @@ -32,9 +32,9 @@ */ void -t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, int level, t8_scheme_cxx_t *ts, t8_gloidx_t *first_local_tree, - t8_gloidx_t *child_in_tree_begin, t8_gloidx_t *last_local_tree, t8_gloidx_t *child_in_tree_end, - int8_t *first_tree_shared) +t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, const int level, t8_scheme_cxx_t *ts, const int multilevel, + t8_gloidx_t *first_local_tree, t8_gloidx_t *element_in_tree_begin, + t8_gloidx_t *last_local_tree, t8_gloidx_t *element_in_tree_end, int8_t *first_tree_shared) { int is_empty; @@ -44,19 +44,19 @@ t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, int level, t8_scheme_cxx_t *ts, t8_gl T8_ASSERT (ts != NULL); *first_local_tree = 0; - if (child_in_tree_begin != NULL) { - *child_in_tree_begin = 0; + if (element_in_tree_begin != NULL) { + *element_in_tree_begin = 0; } *last_local_tree = 0; - if (child_in_tree_end != NULL) { - *child_in_tree_end = 0; + if (element_in_tree_end != NULL) { + *element_in_tree_end = 0; } - t8_gloidx_t global_num_children; - t8_gloidx_t first_global_child; - t8_gloidx_t child_in_tree_begin_temp; - t8_gloidx_t last_global_child; - t8_gloidx_t children_per_tree = 0; + t8_gloidx_t global_num_elements; + t8_gloidx_t first_global_element; + t8_gloidx_t element_in_tree_begin_temp; + t8_gloidx_t last_global_element; + t8_gloidx_t elements_per_tree = 0; #ifdef T8_ENABLE_DEBUG t8_gloidx_t prev_last_tree = -1; #endif @@ -64,7 +64,7 @@ t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, int level, t8_scheme_cxx_t *ts, t8_gl t8_eclass_scheme_c *tree_scheme; /* Compute the number of children on level in each tree */ - global_num_children = 0; + global_num_elements = 0; for (tree_class = T8_ECLASS_ZERO; tree_class < T8_ECLASS_COUNT; ++tree_class) { /* We iterate over each element class and get the number of children for this * tree class. @@ -72,52 +72,54 @@ t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, int level, t8_scheme_cxx_t *ts, t8_gl if (cmesh->num_trees_per_eclass[tree_class] > 0) { tree_scheme = ts->eclass_schemes[tree_class]; T8_ASSERT (tree_scheme != NULL); - children_per_tree = tree_scheme->t8_element_count_leaves_from_root (level); - T8_ASSERT (children_per_tree >= 0); - global_num_children += cmesh->num_trees_per_eclass[tree_class] * children_per_tree; + if (!multilevel) { + elements_per_tree = tree_scheme->t8_element_count_leaves_from_root (level); + } + else { + elements_per_tree = tree_scheme->t8_element_count_elements_from_root (level); + } + T8_ASSERT (elements_per_tree >= 0); + global_num_elements += cmesh->num_trees_per_eclass[tree_class] * elements_per_tree; } } - T8_ASSERT (children_per_tree != 0); + T8_ASSERT (elements_per_tree != 0); if (cmesh->mpirank == 0) { - first_global_child = 0; - if (child_in_tree_begin != NULL) { - *child_in_tree_begin = 0; - } + first_global_element = 0; } else { /* The first global child of processor p * with P total processor is (the biggest int smaller than) - * (total_num_children * p) / P + * (total_num_elements * p) / P * We cast to long double and double first to prevent integer overflow. */ - first_global_child = ((long double) global_num_children * cmesh->mpirank) / (double) cmesh->mpisize; + first_global_element = ((long double) global_num_elements * cmesh->mpirank) / (double) cmesh->mpisize; } if (cmesh->mpirank != cmesh->mpisize - 1) { - last_global_child = ((long double) global_num_children * (cmesh->mpirank + 1)) / (double) cmesh->mpisize; + last_global_element = ((long double) global_num_elements * (cmesh->mpirank + 1)) / (double) cmesh->mpisize; } else { - last_global_child = global_num_children; + last_global_element = global_num_elements; } - T8_ASSERT (0 <= first_global_child && first_global_child <= global_num_children); - T8_ASSERT (0 <= last_global_child && last_global_child <= global_num_children); + T8_ASSERT (0 <= first_global_element && first_global_element <= global_num_elements); + T8_ASSERT (0 <= last_global_element && last_global_element <= global_num_elements); - *first_local_tree = first_global_child / children_per_tree; - child_in_tree_begin_temp = first_global_child - *first_local_tree * children_per_tree; - if (child_in_tree_begin != NULL) { - *child_in_tree_begin = child_in_tree_begin_temp; + *first_local_tree = first_global_element / elements_per_tree; + element_in_tree_begin_temp = first_global_element - *first_local_tree * elements_per_tree; + if (element_in_tree_begin != NULL) { + *element_in_tree_begin = element_in_tree_begin_temp; } - *last_local_tree = (last_global_child - 1) / children_per_tree; + *last_local_tree = (last_global_element - 1) / elements_per_tree; - is_empty = *first_local_tree >= *last_local_tree && first_global_child >= last_global_child; + is_empty = *first_local_tree >= *last_local_tree && first_global_element >= last_global_element; if (first_tree_shared != NULL) { #ifdef T8_ENABLE_DEBUG - prev_last_tree = (first_global_child - 1) / children_per_tree; + prev_last_tree = (first_global_element - 1) / elements_per_tree; T8_ASSERT (cmesh->mpirank > 0 || prev_last_tree <= 0); #endif - if (!is_empty && cmesh->mpirank > 0 && child_in_tree_begin_temp > 0) { + if (!is_empty && cmesh->mpirank > 0 && element_in_tree_begin_temp > 0) { /* We exclude empty partitions here, by def their first_tree_shared flag is zero */ /* We also exclude that the previous partition was empty at the beginning of the * partitions array */ @@ -129,20 +131,20 @@ t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, int level, t8_scheme_cxx_t *ts, t8_gl *first_tree_shared = 0; } } - if (child_in_tree_end != NULL) { + if (element_in_tree_end != NULL) { if (*last_local_tree > 0) { - *child_in_tree_end = last_global_child - *last_local_tree * children_per_tree; + *element_in_tree_end = last_global_element - *last_local_tree * elements_per_tree; } else { - *child_in_tree_end = last_global_child; + *element_in_tree_end = last_global_element; } } if (is_empty) { /* This process is empty */ /* We now set the first local tree to the first local tree on the * next nonempty rank, and the last local tree to first - 1 */ - *first_local_tree = last_global_child / children_per_tree; - if (first_global_child % children_per_tree != 0) { + *first_local_tree = last_global_element / elements_per_tree; + if (first_global_element % elements_per_tree != 0) { /* The next nonempty process shares this tree. */ (*first_local_tree)++; } diff --git a/src/t8_cmesh/t8_cmesh_examples.cxx b/src/t8_cmesh/t8_cmesh_examples.cxx index c6330d27bb..89405c613b 100644 --- a/src/t8_cmesh/t8_cmesh_examples.cxx +++ b/src/t8_cmesh/t8_cmesh_examples.cxx @@ -3204,7 +3204,7 @@ t8_cmesh_new_spherical_shell (t8_eclass_t eclass, t8_geometry_c *geometry, /* Create 2D quadrangulated spherical surface of given refinement level per patch. */ t8_forest_t forest = t8_forest_new_uniform (inner_sphere_creator (inner_radius, local_comm), - t8_scheme_new_default_cxx (), num_levels, 0, local_comm); + t8_scheme_new_default_cxx (), num_levels, 0, 0, local_comm); /* clang-format off */ const int ntrees = t8_forest_get_local_num_elements (forest) * num_layers; /* Number of 3D cmesh elements resp. trees. */ diff --git a/src/t8_cmesh/t8_cmesh_partition.cxx b/src/t8_cmesh/t8_cmesh_partition.cxx index c4654fe0be..54396b840c 100644 --- a/src/t8_cmesh/t8_cmesh_partition.cxx +++ b/src/t8_cmesh/t8_cmesh_partition.cxx @@ -1560,8 +1560,8 @@ t8_cmesh_partition (t8_cmesh_t cmesh, sc_MPI_Comm comm) T8_ASSERT (cmesh->tree_offsets == NULL); ts = cmesh->set_partition_scheme; /* The refinement scheme */ T8_ASSERT (ts != NULL); - t8_cmesh_uniform_bounds (cmesh_from, cmesh->set_partition_level, ts, &cmesh->first_tree, NULL, &last_tree, NULL, - &cmesh->first_tree_shared); + t8_cmesh_uniform_bounds (cmesh_from, cmesh->set_partition_level, ts, cmesh->set_partition_multilevel, + &cmesh->first_tree, NULL, &last_tree, NULL, &cmesh->first_tree_shared); cmesh->num_local_trees = last_tree - cmesh->first_tree + 1; /* Compute the tree offset */ t8_cmesh_gather_treecount_nocommit (cmesh, comm); diff --git a/src/t8_cmesh/t8_cmesh_types.h b/src/t8_cmesh/t8_cmesh_types.h index 854d80c471..fc18bef249 100644 --- a/src/t8_cmesh/t8_cmesh_types.h +++ b/src/t8_cmesh/t8_cmesh_types.h @@ -98,19 +98,21 @@ typedef struct t8_cmesh t8_scheme_cxx_t *set_partition_scheme; /**< If the cmesh is to be partitioned according to a uniform level, the scheme that describes the refinement pattern. See \ref t8_cmesh_set_partition. */ - int8_t set_partition_level; /**< Non-negative if the cmesh should be partitioned from an already existing cmesh + int8_t set_partition_level; /**< Non-negative if the cmesh should be partitioned from an already existing cmesh with an assumed \a level uniform mesh underneath. */ - struct t8_cmesh *set_from; /**< If this cmesh shall be derived from an + int set_partition_multilevel; /**< Positive if the cmesh should be partitioned from an already existing cmesh + with an assumed multilevel uniform mesh underneath. */ + struct t8_cmesh *set_from; /**< If this cmesh shall be derived from an existing cmesh by copy or more elaborate modification, we store a pointer to this other cmesh here. */ - int mpirank; /**< Number of this MPI process. */ - int mpisize; /**< Number of MPI processes. */ - t8_refcount_t rc; /**< The reference count of the cmesh. */ - t8_gloidx_t num_trees; /**< The global number of trees */ - t8_locidx_t num_local_trees; /**< If partitioned the number of trees on this process. + int mpirank; /**< Number of this MPI process. */ + int mpisize; /**< Number of MPI processes. */ + t8_refcount_t rc; /**< The reference count of the cmesh. */ + t8_gloidx_t num_trees; /**< The global number of trees */ + t8_locidx_t num_local_trees; /**< If partitioned the number of trees on this process. Otherwise the global number of trees. */ - t8_locidx_t num_ghosts; /**< If partitioned the number of neighbor trees + t8_locidx_t num_ghosts; /**< If partitioned the number of neighbor trees owned by different processes. */ /* TODO: wouldnt a local num_trees_per_eclass be better? * only as an additional info. we need the global count. i.e. for forest_maxlevel computation. diff --git a/src/t8_element_c_interface.cxx b/src/t8_element_c_interface.cxx index 3cbd1be0ac..345b88b99d 100644 --- a/src/t8_element_c_interface.cxx +++ b/src/t8_element_c_interface.cxx @@ -301,11 +301,12 @@ t8_element_last_descendant_face (const t8_eclass_scheme_c *ts, const t8_element_ } void -t8_element_set_linear_id (const t8_eclass_scheme_c *ts, t8_element_t *elem, int level, t8_linearidx_t id) +t8_element_set_linear_id (const t8_eclass_scheme_c *ts, t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) { T8_ASSERT (ts != NULL); - ts->t8_element_set_linear_id (elem, level, id); + ts->t8_element_set_linear_id (elem, level, id, multilevel); } int @@ -334,11 +335,11 @@ t8_element_shape (const t8_eclass_scheme_c *ts, const t8_element_t *elem) } t8_linearidx_t -t8_element_get_linear_id (const t8_eclass_scheme_c *ts, const t8_element_t *elem, int level) +t8_element_get_linear_id (const t8_eclass_scheme_c *ts, const t8_element_t *elem, const int level, const int multilevel) { T8_ASSERT (ts != NULL); - return ts->t8_element_get_linear_id (elem, level); + return ts->t8_element_get_linear_id (elem, level, multilevel); } void @@ -358,11 +359,12 @@ t8_element_last_descendant (const t8_eclass_scheme_c *ts, const t8_element_t *el } void -t8_element_successor (const t8_eclass_scheme_c *ts, const t8_element_t *elem1, t8_element_t *elem2) +t8_element_successor (const t8_eclass_scheme_c *ts, const t8_element_t *elem1, t8_element_t *elem2, const int level, + const int multilevel) { T8_ASSERT (ts != NULL); - ts->t8_element_successor (elem1, elem2); + ts->t8_element_successor (elem1, elem2, level, multilevel); } void @@ -390,6 +392,14 @@ t8_element_count_leaves_from_root (const t8_eclass_scheme_c *ts, int level) return ts->t8_element_count_leaves_from_root (level); } +t8_gloidx_t +t8_element_count_elements_from_root (const t8_eclass_scheme_c *ts, int level) +{ + T8_ASSERT (ts != NULL); + + return ts->t8_element_count_elements_from_root (level); +} + #ifdef T8_ENABLE_DEBUG int t8_element_is_valid (const t8_eclass_scheme_c *ts, const t8_element_t *elem) diff --git a/src/t8_element_c_interface.h b/src/t8_element_c_interface.h index f1fb8cea52..7a50d22e0c 100644 --- a/src/t8_element_c_interface.h +++ b/src/t8_element_c_interface.h @@ -488,20 +488,25 @@ t8_element_shape (const t8_eclass_scheme_c *ts, const t8_element_t *elem); * \param [in,out] elem The element whose entries will be set. * \param [in] level The level of the uniform refinement to consider. * \param [in] id The linear id. + * \param [in] multilevel If true, the linear id is considered a multilevel id. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' + * or 0 <= id < 'number of elements in the uniform refinement' if multilevel is true. */ void -t8_element_set_linear_id (const t8_eclass_scheme_c *ts, t8_element_t *elem, int level, t8_linearidx_t id); +t8_element_set_linear_id (const t8_eclass_scheme_c *ts, t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel); /** Compute the linear id of a given element in a hypothetical uniform * refinement of a given level. - * \param [in] ts Implementation of a class scheme. - * \param [in] elem The element whose id we compute. - * \param [in] level The level of the uniform refinement to consider. - * \return The linear id of the element. + * \param [in] ts Implementation of a class scheme. + * \param [in] elem The element whose id we compute. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel If true, the linear id is transformed to a multilevel id. + * \return The linear id of the element. */ t8_linearidx_t -t8_element_get_linear_id (const t8_eclass_scheme_c *ts, const t8_element_t *elem, int level); +t8_element_get_linear_id (const t8_eclass_scheme_c *ts, const t8_element_t *elem, const int level, + const int multilevel); /** Compute the first descendant of a given element. * \param [in] ts Implementation of a class scheme. @@ -526,9 +531,11 @@ t8_element_last_descendant (const t8_eclass_scheme_c *ts, const t8_element_t *el * \param [in] elem1 The element whose successor should be constructed. * \param [in,out] elem2 The element whose entries will be set. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ void -t8_element_successor (const t8_eclass_scheme_c *ts, const t8_element_t *elem1, t8_element_t *elem2); +t8_element_successor (const t8_eclass_scheme_c *ts, const t8_element_t *elem1, t8_element_t *elem2, const int level, + const int multilevel); /** Compute the coordinates of a given element vertex inside a reference tree * that is embedded into [0,1]^d (d = dimension). @@ -570,6 +577,18 @@ t8_element_count_leaves (const t8_eclass_scheme_c *ts, const t8_element_t *t, in t8_gloidx_t t8_element_count_leaves_from_root (const t8_eclass_scheme_c *ts, int level); +/** Count how many elements (including ancestors) of a given uniform level the root element will produce. + * \param [in] ts Implementation of a class scheme. + * \param [in] level A refinement level. + * \return The value of \ref t8_element_count_leaves if the input element + * is the root (level 0) element. + * + * This is a convenience function, and can be implemented via + * \ref t8_element_count_leaves. + */ +t8_gloidx_t +t8_element_count_elements_from_root (const t8_eclass_scheme_c *ts, int level); + #ifdef T8_ENABLE_DEBUG /** Query whether a given element can be considered as 'valid' and it is * safe to perform any of the above algorithms on it. diff --git a/src/t8_element_cxx.hxx b/src/t8_element_cxx.hxx index 7085984311..0e0bcb015d 100644 --- a/src/t8_element_cxx.hxx +++ b/src/t8_element_cxx.hxx @@ -512,13 +512,15 @@ struct t8_eclass_scheme /** Initialize the entries of an allocated element according to a * given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const = 0; /** Compute the linear id of a given element in a hypothetical uniform @@ -528,7 +530,7 @@ struct t8_eclass_scheme * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const = 0; /** Compute the first descendant of a given element. @@ -554,9 +556,11 @@ struct t8_eclass_scheme /** Construct the successor in a uniform refinement of a given element. * \param [in] elem1 The element whose successor should be constructed. * \param [in,out] elem2 The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ virtual void - t8_element_successor (const t8_element_t *t, t8_element_t *s) const + t8_element_successor (const t8_element_t *t, t8_element_t *s, const int level, const int multilevel) const = 0; /** Compute the coordinates of a given element vertex inside a reference tree @@ -614,6 +618,18 @@ struct t8_eclass_scheme t8_element_count_leaves_from_root (int level) const = 0; + /** Count how many elements (including ancestors) of a given uniform level the root element will produce. + * \param [in] level A refinement level. + * \return The value of \ref t8_element_count_leaves if the input element + * is the root (level 0) element. + * + * This is a convenience function, and can be implemented via + * \ref t8_element_count_leaves. + */ + virtual t8_gloidx_t + t8_element_count_elements_from_root (int level) const + = 0; + #ifdef T8_ENABLE_DEBUG /** Query whether a given element can be considered as 'valid' and it is * safe to perform any of the above algorithms on it. diff --git a/src/t8_forest/t8_forest.c b/src/t8_forest/t8_forest.c index 7a0a6c397c..1aaaf67dc9 100644 --- a/src/t8_forest/t8_forest.c +++ b/src/t8_forest/t8_forest.c @@ -107,6 +107,10 @@ t8_forest_set_cmesh (t8_forest_t forest, t8_cmesh_t cmesh, sc_MPI_Comm comm) } if (cmesh != NULL) { T8_ASSERT (t8_cmesh_comm_is_valid (cmesh, comm)); + /* If the cmesh is set for partition check if it is partitioned for multilevel as well */ + if (cmesh->set_partition_level > -1) { + T8_ASSERT (forest->multilevel == cmesh->set_partition_multilevel); + } } forest->cmesh = cmesh; do_dup = 0; @@ -139,6 +143,18 @@ t8_forest_set_level (t8_forest_t forest, int level) forest->set_level = level; } +void +t8_forest_set_multilevel (t8_forest_t forest) +{ + T8_ASSERT (forest != NULL); + T8_ASSERT (forest->rc.refcount > 0); + T8_ASSERT (!forest->committed); + T8_ASSERT (forest->set_from == NULL); + T8_ASSERT (forest->multilevel == 0); + + forest->multilevel = 1; +} + void t8_forest_set_copy (t8_forest_t forest, const t8_forest_t set_from) { @@ -454,6 +470,8 @@ t8_forest_commit (t8_forest_t forest) T8_ASSERT (forest->set_level <= forest->maxlevel); /* populate a new forest with tree and quadrant objects */ if (t8_forest_refines_irregular (forest) && forest->set_level > 0) { + /* Multilevel is not yet compatible with irregular forests */ + T8_ASSERT (forest->multilevel == 0); /* On root level we will also use the normal algorithm */ t8_forest_populate_irregular (forest); } @@ -499,6 +517,7 @@ t8_forest_commit (t8_forest_t forest) forest->cmesh = forest->set_from->cmesh; forest->scheme_cxx = forest->set_from->scheme_cxx; forest->global_num_trees = forest->set_from->global_num_trees; + forest->multilevel = forest->set_from->multilevel; /* Compute the maximum allowed refinement level */ t8_forest_compute_maxlevel (forest); @@ -1406,7 +1425,7 @@ t8_forest_write_vtk (t8_forest_t forest, const char *fileprefix) t8_forest_t t8_forest_new_uniform (t8_cmesh_t cmesh, t8_scheme_cxx_t *scheme, const int level, const int do_face_ghost, - sc_MPI_Comm comm) + const int multilevel, sc_MPI_Comm comm) { t8_forest_t forest; @@ -1417,6 +1436,8 @@ t8_forest_new_uniform (t8_cmesh_t cmesh, t8_scheme_cxx_t *scheme, const int leve /* Initialize the forest */ t8_forest_init (&forest); /* Set the cmesh, scheme and level */ + if (multilevel) + t8_forest_set_multilevel (forest); t8_forest_set_cmesh (forest, cmesh, comm); t8_forest_set_scheme (forest, scheme); t8_forest_set_level (forest, level); diff --git a/src/t8_forest/t8_forest_cxx.cxx b/src/t8_forest/t8_forest_cxx.cxx index 464457228d..55441b72e8 100644 --- a/src/t8_forest/t8_forest_cxx.cxx +++ b/src/t8_forest/t8_forest_cxx.cxx @@ -1154,9 +1154,9 @@ t8_forest_compute_desc (t8_forest_t forest) void t8_forest_populate (t8_forest_t forest) { - t8_gloidx_t child_in_tree_begin; - t8_gloidx_t child_in_tree_end; - t8_locidx_t count_elements; + t8_gloidx_t element_in_tree_begin; + t8_gloidx_t element_in_tree_end; + t8_locidx_t count_tree_elements; t8_locidx_t num_tree_elements; t8_locidx_t num_local_trees; t8_gloidx_t jt, first_ctree; @@ -1171,12 +1171,13 @@ t8_forest_populate (t8_forest_t forest) SC_CHECK_ABORT (forest->set_level <= forest->maxlevel, "Given refinement level exceeds the maximum.\n"); /* TODO: create trees and quadrants according to uniform refinement */ - t8_cmesh_uniform_bounds (forest->cmesh, forest->set_level, forest->scheme_cxx, &forest->first_local_tree, - &child_in_tree_begin, &forest->last_local_tree, &child_in_tree_end, NULL); + t8_cmesh_uniform_bounds (forest->cmesh, forest->set_level, forest->scheme_cxx, forest->multilevel, + &forest->first_local_tree, &element_in_tree_begin, &forest->last_local_tree, + &element_in_tree_end, NULL); /* True if the forest has no elements */ is_empty = forest->first_local_tree > forest->last_local_tree - || (forest->first_local_tree == forest->last_local_tree && child_in_tree_begin >= child_in_tree_end); + || (forest->first_local_tree == forest->last_local_tree && element_in_tree_begin >= element_in_tree_end); cmesh_first_tree = t8_cmesh_get_first_treeid (forest->cmesh); cmesh_last_tree = cmesh_first_tree + t8_cmesh_get_num_local_trees (forest->cmesh) - 1; @@ -1192,7 +1193,7 @@ t8_forest_populate (t8_forest_t forest) /* This processor is empty * we still set the tree array to store 0 as the number of trees here */ forest->trees = sc_array_new (sizeof (t8_tree_struct_t)); - count_elements = 0; + count_tree_elements = 0; /* Set the first local tree larger than the last local tree to * indicate empty forest */ forest->first_local_tree = forest->last_local_tree + 1; @@ -1202,34 +1203,46 @@ t8_forest_populate (t8_forest_t forest) num_local_trees = forest->last_local_tree - forest->first_local_tree + 1; forest->trees = sc_array_new_count (sizeof (t8_tree_struct_t), num_local_trees); first_ctree = t8_cmesh_get_first_treeid (forest->cmesh); - for (jt = forest->first_local_tree, count_elements = 0; jt <= forest->last_local_tree; jt++) { + /* Iterate over each tree */ + for (jt = forest->first_local_tree, count_tree_elements = 0; jt <= forest->last_local_tree; jt++) { tree = (t8_tree_t) t8_sc_array_index_locidx (forest->trees, jt - forest->first_local_tree); tree_class = tree->eclass = t8_cmesh_get_tree_class (forest->cmesh, jt - first_ctree); - tree->elements_offset = count_elements; + tree->elements_offset = count_tree_elements; eclass_scheme = forest->scheme_cxx->eclass_schemes[tree_class]; T8_ASSERT (eclass_scheme != NULL); telements = &tree->elements; /* calculate first and last element on this tree */ - start = (jt == forest->first_local_tree) ? child_in_tree_begin : 0; - end = (jt == forest->last_local_tree) ? child_in_tree_end - : eclass_scheme->t8_element_count_leaves_from_root (forest->set_level); + start = (jt == forest->first_local_tree) ? element_in_tree_begin : 0; + if (jt == forest->last_local_tree) { + end = element_in_tree_end; + } + else { + if (!forest->multilevel) + end = eclass_scheme->t8_element_count_leaves_from_root (forest->set_level); + else + end = eclass_scheme->t8_element_count_elements_from_root (forest->set_level); + } num_tree_elements = end - start; T8_ASSERT (num_tree_elements > 0); /* Allocate elements for this processor. */ t8_element_array_init_size (telements, eclass_scheme, num_tree_elements); element = t8_element_array_index_locidx (telements, 0); - eclass_scheme->t8_element_set_linear_id (element, forest->set_level, start); - count_elements++; - for (et = start + 1; et < end; et++, count_elements++) { + eclass_scheme->t8_element_set_linear_id (element, forest->multilevel ? 0 : forest->set_level, start, + forest->multilevel); + count_tree_elements++; + for (et = start + 1; et < end; et++, count_tree_elements++) { element_succ = t8_element_array_index_locidx (telements, et - start); - T8_ASSERT (eclass_scheme->t8_element_level (element) == forest->set_level); - eclass_scheme->t8_element_successor (element, element_succ); + if (!forest->multilevel) + T8_ASSERT (eclass_scheme->t8_element_level (element) == forest->set_level); + else + T8_ASSERT (eclass_scheme->t8_element_level (element) <= forest->set_level); + eclass_scheme->t8_element_successor (element, element_succ, forest->set_level, forest->multilevel); /* TODO: process elements here */ element = element_succ; } } } - forest->local_num_elements = count_elements; + forest->local_num_elements = count_tree_elements; /* TODO: if no tree has pyramid type we can optimize this to global_num_elements = global_num_trees * 2^(dim*level) */ t8_forest_comm_global_num_elements (forest); /* TODO: figure out global_first_position, global_first_quadrant without comm */ @@ -1439,7 +1452,8 @@ t8_forest_copy_trees (t8_forest_t forest, t8_forest_t from, int copy_elements) */ /* TODO: should return t8_locidx_t */ static t8_locidx_t -t8_forest_bin_search_lower (t8_element_array_t *elements, t8_linearidx_t element_id, int maxlevel) +t8_forest_bin_search_lower (t8_element_array_t *elements, const t8_linearidx_t element_id, const int maxlevel, + const int multilevel) { t8_element_t *query; t8_linearidx_t query_id; @@ -1450,7 +1464,7 @@ t8_forest_bin_search_lower (t8_element_array_t *elements, t8_linearidx_t element /* At first, we check whether any element has smaller id than the * given one. */ query = t8_element_array_index_int (elements, 0); - query_id = ts->t8_element_get_linear_id (query, maxlevel); + query_id = ts->t8_element_get_linear_id (query, maxlevel, multilevel); if (query_id > element_id) { /* No element has id smaller than the given one */ return -1; @@ -1462,7 +1476,7 @@ t8_forest_bin_search_lower (t8_element_array_t *elements, t8_linearidx_t element while (low < high) { guess = (low + high + 1) / 2; query = t8_element_array_index_int (elements, guess); - query_id = ts->t8_element_get_linear_id (query, maxlevel); + query_id = ts->t8_element_get_linear_id (query, maxlevel, multilevel); if (query_id == element_id) { /* we are done */ return guess; @@ -1832,13 +1846,13 @@ t8_forest_leaf_face_neighbors_ext (t8_forest_t forest, t8_locidx_t ltreeid, cons if (!different_owners) { /* The face neighbors belong to the same process, we thus need to determine * if they are leaves or their parent or grandparent. */ - neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leaves[0], forest->maxlevel); + neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leaves[0], forest->maxlevel, forest->multilevel); if (owners[0] != forest->mpirank) { /* The elements are ghost elements of the same owner */ element_array = t8_forest_ghost_get_tree_elements (forest, lghost_treeid); /* Find the index in element_array of the leaf ancestor of the first neighbor. * This is either the neighbor itself or its parent, or its grandparent */ - element_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); + element_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel, forest->multilevel); T8_ASSERT (element_index >= 0); /* Get the element */ @@ -1854,7 +1868,7 @@ t8_forest_leaf_face_neighbors_ext (t8_forest_t forest, t8_locidx_t ltreeid, cons element_array = t8_forest_get_tree_element_array (forest, lneigh_treeid); /* Find the index in element_array of the leaf ancestor of the first neighbor. * This is either the neighbor itself or its parent, or its grandparent */ - element_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); + element_index = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel, forest->multilevel); /* Get the element */ ancestor = t8_forest_get_tree_element (t8_forest_get_tree (forest, lneigh_treeid), element_index); /* Add the element offset of this tree to the index */ @@ -1909,14 +1923,15 @@ t8_forest_leaf_face_neighbors_ext (t8_forest_t forest, t8_locidx_t ltreeid, cons element_indices = *pelement_indices; for (ineigh = 0; ineigh < num_children_at_face; ineigh++) { /* Compute the linear id at maxlevel of the neighbor leaf */ - neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leaves[ineigh], forest->maxlevel); + neigh_id = neigh_scheme->t8_element_get_linear_id (neighbor_leaves[ineigh], forest->maxlevel, forest->multilevel); /* Get a pointer to the element array in which the neighbor lies and search for the element's index in this array. * This is either the local leaf array of the local tree or the corresponding leaf array in the ghost structure */ if (owners[ineigh] == forest->mpirank) { /* The neighbor is a local leaf */ element_array = t8_forest_get_tree_element_array (forest, lneigh_treeid); /* Find the index of the neighbor in the array */ - element_indices[ineigh] = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); + element_indices[ineigh] + = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel, forest->multilevel); T8_ASSERT (element_indices[ineigh] >= 0); /* We have to add the tree's element offset to the index found to get the actual local element id */ element_indices[ineigh] += t8_forest_get_tree_element_offset (forest, lneigh_treeid); @@ -1934,7 +1949,8 @@ t8_forest_leaf_face_neighbors_ext (t8_forest_t forest, t8_locidx_t ltreeid, cons /* The neighbor is a ghost */ element_array = t8_forest_ghost_get_tree_elements (forest, lghost_treeid); /* Find the index of the neighbor in the array */ - element_indices[ineigh] = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel); + element_indices[ineigh] + = t8_forest_bin_search_lower (element_array, neigh_id, forest->maxlevel, forest->multilevel); #if T8_ENABLE_DEBUG /* We check whether the element is really the element at this local id */ @@ -2067,12 +2083,12 @@ t8_forest_element_check_owner (t8_forest_t forest, t8_element_t *element, t8_glo if (!element_is_desc) { ts->t8_element_new (1, &first_desc); ts->t8_element_first_descendant (element, first_desc, forest->maxlevel); - first_desc_id = ts->t8_element_get_linear_id (first_desc, forest->maxlevel); + first_desc_id = ts->t8_element_get_linear_id (first_desc, forest->maxlevel, forest->multilevel); ts->t8_element_destroy (1, &first_desc); } else { /* The element is its own first descendant */ - first_desc_id = ts->t8_element_get_linear_id (element, forest->maxlevel); + first_desc_id = ts->t8_element_get_linear_id (element, forest->maxlevel, forest->multilevel); } /* Get the id of the trees first descendant and the first descendant * of the next nonempty rank */ @@ -2191,7 +2207,7 @@ t8_forest_element_find_owner_ext (t8_forest_t forest, t8_gloidx_t gtreeid, t8_el const t8_gloidx_t *first_trees = t8_shmem_array_get_gloidx_array (forest->tree_offsets); first_descs = (t8_linearidx_t *) t8_shmem_array_get_array (forest->global_first_desc); /* Compute the linear id of the element's first descendant */ - element_desc_id = ts->t8_element_get_linear_id (first_desc, ts->t8_element_level (first_desc)); + element_desc_id = ts->t8_element_get_linear_id (first_desc, ts->t8_element_level (first_desc), forest->multilevel); /* Get a pointer to the element offset array */ const t8_gloidx_t *element_offsets = t8_shmem_array_get_gloidx_array (forest->element_offsets); @@ -2353,7 +2369,7 @@ t8_forest_element_find_owner_old (t8_forest_t forest, t8_gloidx_t gtreeid, t8_el ts->t8_element_new (1, &element_first_desc); ts->t8_element_first_descendant (element, element_first_desc, forest->maxlevel); /* Compute the linear of the first descendant */ - element_desc_lin_id = ts->t8_element_get_linear_id (element_first_desc, forest->maxlevel); + element_desc_lin_id = ts->t8_element_get_linear_id (element_first_desc, forest->maxlevel, forest->multilevel); /* The first owner of the tree may not have the tree as its first tree and * thus its first_descendant entry may not relate to this tree. @@ -2677,7 +2693,7 @@ t8_forest_element_has_leaf_desc (t8_forest_t forest, t8_gloidx_t gtreeid, const ts->t8_element_new (1, &last_desc); /* TODO: set level in last_descendant */ ts->t8_element_last_descendant (element, last_desc, forest->maxlevel); - last_desc_id = ts->t8_element_get_linear_id (last_desc, forest->maxlevel); + last_desc_id = ts->t8_element_get_linear_id (last_desc, forest->maxlevel, forest->multilevel); /* Get the level of the element */ level = ts->t8_element_level (element); /* Get the local id of the tree. If the tree is not a local tree, @@ -2688,14 +2704,15 @@ t8_forest_element_has_leaf_desc (t8_forest_t forest, t8_gloidx_t gtreeid, const /* Get the elements */ elements = t8_forest_get_tree_element_array (forest, ltreeid); - index = t8_forest_bin_search_lower (elements, last_desc_id, forest->maxlevel); + index = t8_forest_bin_search_lower (elements, last_desc_id, forest->maxlevel, forest->multilevel); if (index >= 0) { /* There exists an element in the array with id <= last_desc_id, * If also elem_id < id, then we found a true decsendant of element */ elem_found = t8_element_array_index_locidx (elements, index); - elem_id = ts->t8_element_get_linear_id (elem_found, forest->maxlevel); + elem_id = ts->t8_element_get_linear_id (elem_found, forest->maxlevel, forest->multilevel); level_found = ts->t8_element_level (elem_found); - if (ts->t8_element_get_linear_id (element, forest->maxlevel) <= elem_id && level < level_found) { + if (ts->t8_element_get_linear_id (element, forest->maxlevel, 0) <= elem_id && level < level_found, + forest->multilevel) { /* The element is a true descendant */ T8_ASSERT (ts->t8_element_level (elem_found) > ts->t8_element_level (element)); /* clean-up */ @@ -2710,14 +2727,16 @@ t8_forest_element_has_leaf_desc (t8_forest_t forest, t8_gloidx_t gtreeid, const if (ghost_treeid >= 0) { /* The tree is a ghost tree */ elements = t8_forest_ghost_get_tree_elements (forest, ghost_treeid); - index = t8_forest_bin_search_lower (elements, last_desc_id, forest->maxlevel); + index = t8_forest_bin_search_lower (elements, last_desc_id, forest->maxlevel, forest->multilevel); if (index >= 0) { /* There exists an element in the array with id <= last_desc_id, * If also elem_id < id, then we found a true decsendant of element */ elem_found = t8_element_array_index_int (elements, index); - elem_id = ts->t8_element_get_linear_id (elem_found, forest->maxlevel); + elem_id = ts->t8_element_get_linear_id (elem_found, forest->maxlevel, forest->multilevel); level_found = ts->t8_element_level (elem_found); - if (ts->t8_element_get_linear_id (element, forest->maxlevel) <= elem_id && level < level_found) { + if (ts->t8_element_get_linear_id (element, forest->maxlevel, forest->multilevel) <= elem_id + && level < level_found, + 0) { /* The element is a true descendant */ T8_ASSERT (ts->t8_element_level (elem_found) > ts->t8_element_level (element)); /* clean-up */ diff --git a/src/t8_forest/t8_forest_general.h b/src/t8_forest/t8_forest_general.h index 7e39fa9c45..c0843820e2 100644 --- a/src/t8_forest/t8_forest_general.h +++ b/src/t8_forest/t8_forest_general.h @@ -213,6 +213,14 @@ t8_forest_set_scheme (t8_forest_t forest, t8_scheme_cxx_t *scheme); void t8_forest_set_level (t8_forest_t forest, int level); +/** Set the multilevel flag of a forest. This can only be done with an empty forest + * which is not derived from another forest. It cannot be reversed. + * The forest will now save all ancestors in the SFC as well as the leaves. + * \param [in, out] forest + */ +void +t8_forest_set_multilevel (t8_forest_t forest); + /** Set a forest as source for copying on committing. * By default, the forest takes ownership of the source \b from such that it will * be destroyed on calling \ref t8_forest_commit. To keep ownership of \b @@ -802,19 +810,20 @@ t8_forest_element_points_inside (t8_forest_t forest, t8_locidx_t ltreeid, const /* TODO: if set level and partition/adapt/balance all give NULL, then * refine uniformly and partition/adapt/balance the unfiform forest. */ /** Build a uniformly refined forest on a coarse mesh. - * \param [in] cmesh A coarse mesh. - * \param [in] scheme An eclass scheme. - * \param [in] level An initial uniform refinement level. + * \param [in] cmesh A coarse mesh. + * \param [in] scheme An eclass scheme. + * \param [in] level An initial uniform refinement level. * \param [in] do_face_ghost If true, a layer of ghost elements is created for the forest. - * \param [in] comm MPI communicator to use. - * \return A uniform forest with coarse mesh \a cmesh, eclass_scheme - * \a scheme and refinement level \a level. + * \param [in] multilevel Run the SFC not just the leaves, but the whole tree. + * \param [in] comm MPI communicator to use. + * \return A uniform forest with coarse mesh \a cmesh, eclass_scheme + * \a scheme and refinement level \a level. * \note This is equivalent to calling \ref t8_forest_init, \ref t8_forest_set_cmesh, * \ref t8_forest_set_scheme, \ref t8_forest_set_level, and \ref t8_forest_commit. */ t8_forest_t t8_forest_new_uniform (t8_cmesh_t cmesh, t8_scheme_cxx_t *scheme, const int level, const int do_face_ghost, - sc_MPI_Comm comm); + const int multilevel, sc_MPI_Comm comm); /** Build a adapted forest from another forest. * \param [in] forest_from The forest to refine diff --git a/src/t8_forest/t8_forest_ghost.cxx b/src/t8_forest/t8_forest_ghost.cxx index 64ba73fb77..44991b0694 100644 --- a/src/t8_forest/t8_forest_ghost.cxx +++ b/src/t8_forest/t8_forest_ghost.cxx @@ -474,7 +474,9 @@ t8_ghost_add_remote (t8_forest_t forest, t8_forest_ghost_t ghost, int remote_ran * If so, we add a copy of elem to the array. * Otherwise, we do nothing. */ if (elem_copy == NULL || level != copy_level - || ts->t8_element_get_linear_id (elem_copy, copy_level) != ts->t8_element_get_linear_id (elem, level)) { + || ts->t8_element_get_linear_id (elem_copy, copy_level, forest->multilevel) + != ts->t8_element_get_linear_id (elem, level, forest->multilevel), + 0) { /* Add the element */ elem_copy = t8_element_array_push (&remote_tree->elements); ts->t8_element_copy (elem, elem_copy); diff --git a/src/t8_forest/t8_forest_partition.cxx b/src/t8_forest/t8_forest_partition.cxx index b8ff2cb8a3..1b0dec4977 100644 --- a/src/t8_forest/t8_forest_partition.cxx +++ b/src/t8_forest/t8_forest_partition.cxx @@ -144,7 +144,8 @@ t8_forest_partition_test_desc (t8_forest_t forest) level = ts->t8_element_level (elem_desc); T8_ASSERT (level == ts->t8_element_level (elem_desc)); T8_ASSERT (level == forest->maxlevel); - T8_ASSERT (ts->t8_element_get_linear_id (elem_desc, level) >= first_desc_id); + if (!forest->multilevel) + T8_ASSERT (ts->t8_element_get_linear_id (elem_desc, level, forest->multilevel) >= first_desc_id); } ts->t8_element_destroy (1, &elem_desc); } @@ -236,7 +237,7 @@ t8_forest_partition_test_boundary_element (const t8_forest_t forest) const int level = ts->t8_element_level (element_last_desc); T8_ASSERT (level == ts->t8_element_level (element_last_desc)); T8_ASSERT (level == forest->maxlevel); - const t8_linearidx_t last_desc_id = ts->t8_element_get_linear_id (element_last_desc, level); + const t8_linearidx_t last_desc_id = ts->t8_element_get_linear_id (element_last_desc, level, forest->multilevel); /* Get the first descendant id of rank+1 */ const t8_linearidx_t first_desc_id = *(t8_linearidx_t *) t8_shmem_array_index (forest->global_first_desc, forest->mpirank + 1); @@ -299,7 +300,7 @@ t8_forest_partition_create_first_desc (t8_forest_t forest) ts->t8_element_new (1, &first_desc); ts->t8_element_first_descendant (first_element, first_desc, forest->maxlevel); /* Compute the linear id of the descendant. */ - local_first_desc = ts->t8_element_get_linear_id (first_desc, forest->maxlevel); + local_first_desc = ts->t8_element_get_linear_id (first_desc, forest->maxlevel, forest->multilevel); ts->t8_element_destroy (1, &first_desc); } } diff --git a/src/t8_forest/t8_forest_types.h b/src/t8_forest/t8_forest_types.h index 10f4c84b72..5f1a862223 100644 --- a/src/t8_forest/t8_forest_types.h +++ b/src/t8_forest/t8_forest_types.h @@ -82,25 +82,27 @@ typedef struct t8_forest int do_dup; /**< Communicator shall be duped. */ int dimension; /**< Dimension inferred from \b cmesh. */ int incomplete_trees; /**< Flag to check whether the forest has (potential) incomplete trees. - A tree is incomplete if an element has been removed from it. - Once an element got removed, the flag sets to 1 (true) and stays. - For a committed forest this flag is either true on all ranks or - false on all ranks. */ + A tree is incomplete if an element has been removed from it. + Once an element got removed, the flag sets to 1 (true) and stays. + For a committed forest this flag is either true on all ranks or + false on all ranks. */ + int multilevel; /**< Flag to set the forest to multilevel. The forest will now save all + ancestors in the SFC. Cannot be reversed. */ t8_forest_t set_from; /**< Temporarily store source forest. */ t8_forest_from_t from_method; /**< Method to derive from \b set_from. */ t8_forest_adapt_t set_adapt_fn; /**< refinement and coarsen function. Called when \b from_method - is set to T8_FOREST_FROM_ADAPT. */ + is set to T8_FOREST_FROM_ADAPT. */ int set_adapt_recursive; /**< Flag to decide whether coarsen and refine - are carried out recursive */ + are carried out recursive */ int set_balance; /**< Flag to decide whether to forest will be balance in \ref t8_forest_commit. - See \ref t8_forest_set_balance. - If 0, no balance. If 1 balance with repartitioning, if 2 balance without - repartitioning, \see t8_forest_balance */ + See \ref t8_forest_set_balance. + If 0, no balance. If 1 balance with repartitioning, if 2 balance without + repartitioning, \see t8_forest_balance */ int do_ghost; /**< If True, a ghost layer will be created when the forest is committed. */ t8_ghost_type_t ghost_type; /**< If a ghost layer will be created, the type of neighbors that count as ghost. */ int ghost_algorithm; /**< Controls the algorithm used for ghost. 1 = balanced only. 2 = also unbalanced - 3 = top-down search and unbalanced. */ + 3 = top-down search and unbalanced. */ void *user_data; /**< Pointer for arbitrary user data. \see t8_forest_set_user_data. */ void (*user_function) (); /**< Pointer for arbitrary user function. \see t8_forest_set_user_function. */ void *t8code_data; /**< Pointer for arbitrary data that is used internally. */ diff --git a/src/t8_geometry/t8_geometry_implementations/t8_geometry_lagrange.cxx b/src/t8_geometry/t8_geometry_implementations/t8_geometry_lagrange.cxx index f523a39189..0176202936 100644 --- a/src/t8_geometry/t8_geometry_implementations/t8_geometry_lagrange.cxx +++ b/src/t8_geometry/t8_geometry_implementations/t8_geometry_lagrange.cxx @@ -259,7 +259,7 @@ t8_forest_t t8_lagrange_element::create_uniform_forest (t8_cmesh_t cmesh, uint32_t level) const { t8_forest_t forest; - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, 0, sc_MPI_COMM_WORLD); return forest; } diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx index 0826d81db0..3e335a7a12 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.cxx @@ -153,6 +153,18 @@ t8_default_scheme_common_c::t8_element_count_leaves_from_root (int level) const return count_leaves_from_level (0, level, dim); } +t8_gloidx_t +t8_default_scheme_common_c::t8_element_count_elements_from_root (int level) const +{ + /* Recursion of t8_element_count_leaves_from_root */ + if (level > 0) { + return t8_element_count_leaves_from_root (level) + t8_element_count_elements_from_root (level - 1); + } + else { + return 1; + } +} + #if T8_ENABLE_DEBUG void t8_default_scheme_common_c::t8_element_debug_print (const t8_element_t *elem) const diff --git a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx index 2cb6b25f0d..5b187d782a 100644 --- a/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_common/t8_default_common_cxx.hxx @@ -85,6 +85,14 @@ class t8_default_scheme_common_c: public t8_eclass_scheme_c { virtual t8_gloidx_t t8_element_count_leaves_from_root (int level) const; + /** Count how many elements (including ancestors) of a given uniform level the root element will produce. + * \param [in] level A refinement level. + * \return The value of \ref t8_element_count_leaves if the input element + * is the root (level 0) element. + */ + virtual t8_gloidx_t + t8_element_count_elements_from_root (int level) const; + /** Compute the integer coordinates of a given element vertex. * The default scheme implements the Morton type SFCs. In these SFCs the * elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and diff --git a/src/t8_schemes/t8_default/t8_default_hex/t8_default_hex_cxx.cxx b/src/t8_schemes/t8_default/t8_default_hex/t8_default_hex_cxx.cxx index 3a376b07cb..6b39cf8731 100644 --- a/src/t8_schemes/t8_default/t8_default_hex/t8_default_hex_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_hex/t8_default_hex_cxx.cxx @@ -476,7 +476,8 @@ t8_default_scheme_hex_c::t8_element_face_neighbor_inside (const t8_element_t *el } void -t8_default_scheme_hex_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const +t8_default_scheme_hex_c::t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= HEX_LINEAR_MAXLEVEL); @@ -486,7 +487,8 @@ t8_default_scheme_hex_c::t8_element_set_linear_id (t8_element_t *elem, int level } t8_linearidx_t -t8_default_scheme_hex_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const +t8_default_scheme_hex_c::t8_element_get_linear_id (const t8_element_t *elem, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= HEX_LINEAR_MAXLEVEL); @@ -513,7 +515,8 @@ t8_default_scheme_hex_c::t8_element_last_descendant (const t8_element_t *elem, t } void -t8_default_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2) const +t8_default_scheme_hex_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); diff --git a/src/t8_schemes/t8_default/t8_default_hex/t8_default_hex_cxx.hxx b/src/t8_schemes/t8_default/t8_default_hex/t8_default_hex_cxx.hxx index 18bd1375e3..06a3950145 100644 --- a/src/t8_schemes/t8_default/t8_default_hex/t8_default_hex_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_hex/t8_default_hex_cxx.hxx @@ -455,22 +455,25 @@ struct t8_default_scheme_hex_c: public t8_default_scheme_common_c /** Initialize the entries of an allocated element according to a * given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const; /** Compute the linear id of a given element in a hypothetical uniform * refinement of a given level. * \param [in] elem The element whose id we compute. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const; /** Compute the first descendant of a given element. * \param [in] elem The element whose descendant is computed. @@ -491,12 +494,13 @@ struct t8_default_scheme_hex_c: public t8_default_scheme_common_c t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; /** Construct the successor in a uniform refinement of a given element. - * \param [in] elem1 The element whose successor should be constructed. - * \param [in,out] elem2 The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. + * \param [in] elem The element whose successor should be constructed. + * \param [in,out] succ The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ virtual void - t8_element_successor (const t8_element_t *elem, t8_element_t *succ) const; + t8_element_successor (const t8_element_t *elem, t8_element_t *succ, const int level, const int multilevel) const; /** Get the integer coordinates of the anchor node of an element. * The default scheme implements the Morton type SFCs. In these SFCs the diff --git a/src/t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.cxx b/src/t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.cxx index 93d5de6173..8b7847fcbc 100644 --- a/src/t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.cxx @@ -248,7 +248,8 @@ t8_default_scheme_line_c::t8_element_face_neighbor_inside (const t8_element_t *e } void -t8_default_scheme_line_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const +t8_default_scheme_line_c::t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= T8_DLINE_MAXLEVEL); @@ -258,13 +259,14 @@ t8_default_scheme_line_c::t8_element_set_linear_id (t8_element_t *elem, int leve } void -t8_default_scheme_line_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2) const +t8_default_scheme_line_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); T8_ASSERT (1 <= t8_element_level (elem1) && t8_element_level (elem1) <= T8_DLINE_MAXLEVEL); - t8_dline_successor ((const t8_default_line_t *) elem1, (t8_default_line_t *) elem2, t8_element_level (elem1)); + t8_dline_successor ((const t8_default_line_t *) elem1, (t8_default_line_t *) elem2, level); } void @@ -311,7 +313,8 @@ t8_default_scheme_line_c::t8_element_reference_coords (const t8_element_t *elem, } t8_linearidx_t -t8_default_scheme_line_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const +t8_default_scheme_line_c::t8_element_get_linear_id (const t8_element_t *elem, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= T8_DLINE_MAXLEVEL); diff --git a/src/t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.hxx b/src/t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.hxx index c495e6d4de..1d720c68e9 100644 --- a/src/t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_line/t8_default_line_cxx.hxx @@ -458,22 +458,25 @@ struct t8_default_scheme_line_c: public t8_default_scheme_common_c /** Initialize the entries of an allocated element according to a * given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const; /** Compute the linear id of a given element in a hypothetical uniform * refinement of a given level. * \param [in] elem The element whose id we compute. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const; /** Compute the first descendant of a given element. * \param [in] elem The element whose descendant is computed. @@ -494,12 +497,13 @@ struct t8_default_scheme_line_c: public t8_default_scheme_common_c t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; /** Construct the successor in a uniform refinement of a given element. - * \param [in] elem1 The element whose successor should be constructed. - * \param [in,out] elem2 The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. + * \param [in] elem The element whose successor should be constructed. + * \param [in,out] succ The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ virtual void - t8_element_successor (const t8_element_t *elem, t8_element_t *succ) const; + t8_element_successor (const t8_element_t *elem, t8_element_t *succ, const int level, const int multilevel) const; /** Get the integer coordinates of the anchor node of an element. * The default scheme implements the Morton type SFCs. In these SFCs the diff --git a/src/t8_schemes/t8_default/t8_default_prism/t8_default_prism_cxx.cxx b/src/t8_schemes/t8_default/t8_default_prism/t8_default_prism_cxx.cxx index 93d04c8ce2..bc7a244976 100644 --- a/src/t8_schemes/t8_default/t8_default_prism/t8_default_prism_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_prism/t8_default_prism_cxx.cxx @@ -339,7 +339,8 @@ t8_default_scheme_prism_c::t8_element_face_neighbor_inside (const t8_element_t * } void -t8_default_scheme_prism_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const +t8_default_scheme_prism_c::t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) const { T8_ASSERT (0 <= level && level <= T8_DPRISM_MAXLEVEL); T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << 3 * level); @@ -350,12 +351,13 @@ t8_default_scheme_prism_c::t8_element_set_linear_id (t8_element_t *elem, int lev } void -t8_default_scheme_prism_c::t8_element_successor (const t8_element_t *elem, t8_element_t *s) const +t8_default_scheme_prism_c::t8_element_successor (const t8_element_t *elem, t8_element_t *s, const int level, + const int multilevel) const { T8_ASSERT (1 <= t8_element_level (elem) && t8_element_level (elem) <= T8_DPRISM_MAXLEVEL); T8_ASSERT (t8_element_is_valid (elem)); - t8_dprism_successor ((const t8_default_prism_t *) elem, (t8_default_prism_t *) s, t8_element_level (elem)); + t8_dprism_successor ((const t8_default_prism_t *) elem, (t8_default_prism_t *) s, level); T8_ASSERT (t8_element_is_valid (s)); } @@ -411,7 +413,8 @@ t8_default_scheme_prism_c::t8_element_reference_coords (const t8_element_t *elem } t8_linearidx_t -t8_default_scheme_prism_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const +t8_default_scheme_prism_c::t8_element_get_linear_id (const t8_element_t *elem, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); return t8_dprism_linear_id ((const t8_dprism_t *) elem, level); diff --git a/src/t8_schemes/t8_default/t8_default_prism/t8_default_prism_cxx.hxx b/src/t8_schemes/t8_default/t8_default_prism/t8_default_prism_cxx.hxx index 7b266a9341..859854a5bd 100644 --- a/src/t8_schemes/t8_default/t8_default_prism/t8_default_prism_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_prism/t8_default_prism_cxx.hxx @@ -439,21 +439,25 @@ struct t8_default_scheme_prism_c: public t8_default_scheme_common_c /** Initialize the entries of an allocated element according to a * given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. id must fulfil 0 <= id < 'number of leaves in the uniform refinement' + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. + * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const; /** Compute the linear id of a given element in a hypothetical uniform * refinement of a given level. * \param [in] elem The element whose id we compute. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const; /** Compute the first descendant of a given element. * \param [in] elem The element whose descendant is computed. @@ -472,12 +476,13 @@ struct t8_default_scheme_prism_c: public t8_default_scheme_common_c t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; /** Construct the successor in a uniform refinement of a given element. - * \param [in] elem1 The element whose successor should be constructed. - * \param [in,out] elem2 The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. + * \param [in] elem The element whose successor should be constructed. + * \param [in,out] succ The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ virtual void - t8_element_successor (const t8_element_t *elem, t8_element_t *succ) const; + t8_element_successor (const t8_element_t *elem, t8_element_t *succ, const int level, const int multilevel) const; /** Get the integer coordinates of the anchor node of an element. The default scheme implements the Morton type SFCs. * In these SFCs the elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and L the maximum diff --git a/src/t8_schemes/t8_default/t8_default_prism/t8_dprism_bits.h b/src/t8_schemes/t8_default/t8_default_prism/t8_dprism_bits.h index 6a378e8484..c528a50d9f 100644 --- a/src/t8_schemes/t8_default/t8_default_prism/t8_dprism_bits.h +++ b/src/t8_schemes/t8_default/t8_default_prism/t8_dprism_bits.h @@ -150,7 +150,7 @@ t8_dprism_is_inside_root (t8_dprism_t *p); /** Compute the childid-th child in Morton order of a prism. * \param [in] p Input prism. * \param [in] childid The id of the child, in 0 - 7, in Morton order. - * \param [in,out] child Existing prism whose data will be filled with the date of p's childid-th child. + * \param [in,out] child Existing prism whose data will be filled with the data of p's childid-th child. */ void t8_dprism_child (const t8_dprism_t *p, int childid, t8_dprism_t *child); diff --git a/src/t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid_cxx.cxx b/src/t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid_cxx.cxx index bef41db044..567b511231 100644 --- a/src/t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid_cxx.cxx @@ -236,7 +236,8 @@ t8_default_scheme_pyramid_c::t8_element_level (const t8_element_t *elem) const } void -t8_default_scheme_pyramid_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const +t8_default_scheme_pyramid_c::t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) const { t8_dpyramid_init_linear_id ((t8_dpyramid_t *) elem, level, id); T8_ASSERT (t8_element_is_valid (elem)); @@ -301,7 +302,8 @@ t8_default_scheme_pyramid_c::t8_element_num_face_children (const t8_element_t *e } t8_linearidx_t -t8_default_scheme_pyramid_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const +t8_default_scheme_pyramid_c::t8_element_get_linear_id (const t8_element_t *elem, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); return t8_dpyramid_linear_id ((const t8_dpyramid_t *) elem, level); @@ -333,10 +335,11 @@ t8_default_scheme_pyramid_c::t8_element_parent (const t8_element_t *elem, t8_ele } void -t8_default_scheme_pyramid_c::t8_element_successor (const t8_element_t *elem, t8_element_t *s) const +t8_default_scheme_pyramid_c::t8_element_successor (const t8_element_t *elem, t8_element_t *s, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); - t8_dpyramid_successor ((const t8_dpyramid_t *) elem, (t8_dpyramid_t *) s, t8_element_level (elem)); + t8_dpyramid_successor ((const t8_dpyramid_t *) elem, (t8_dpyramid_t *) s, level); T8_ASSERT (t8_element_is_valid (s)); } diff --git a/src/t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid_cxx.hxx b/src/t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid_cxx.hxx index e852f5803b..fba182911c 100644 --- a/src/t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid_cxx.hxx @@ -430,22 +430,26 @@ struct t8_default_scheme_pyramid_c: public t8_default_scheme_common_c virtual int t8_element_face_neighbor_inside (const t8_element_t *elem, t8_element_t *neigh, int face, int *neigh_face) const; - /** Initialize the entries of an allocated element according to a given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. + /** Initialize the entries of an allocated element according to a + * given linear id in a uniform refinement. + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const; /** Compute the linear id of a given element in a hypothetical uniform refinement of a given level. * \param [in] elem The element whose id we compute. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. (Not implemented yet.) * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const; /** Compute the first descendant of a given element. * \param [in] elem The element whose descendant is computed. @@ -464,12 +468,13 @@ struct t8_default_scheme_pyramid_c: public t8_default_scheme_common_c t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; /** Construct the successor in a uniform refinement of a given element. - * \param [in] elem1 The element whose successor should be constructed. - * \param [in,out] elem2 The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. + * \param [in] elem The element whose successor should be constructed. + * \param [in,out] succ The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. (Not implemented yet.) */ virtual void - t8_element_successor (const t8_element_t *elem, t8_element_t *succ) const; + t8_element_successor (const t8_element_t *elem, t8_element_t *succ, const int level, const int multilevel) const; /** Get the integer coordinates of the anchor node of an element. The default scheme implements the Morton type SFCs. * In these SFCs the elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and L the maximum diff --git a/src/t8_schemes/t8_default/t8_default_quad/t8_default_quad_cxx.cxx b/src/t8_schemes/t8_default/t8_default_quad/t8_default_quad_cxx.cxx index 92a5b1b360..f692d92574 100644 --- a/src/t8_schemes/t8_default/t8_default_quad/t8_default_quad_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_quad/t8_default_quad_cxx.cxx @@ -31,7 +31,7 @@ T8_EXTERN_C_BEGIN (); /* This function is used by other element functions and we thus need to * declare it up here */ t8_linearidx_t -t8_element_get_linear_id (const t8_element_t *elem, int level); +t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel); #ifdef T8_ENABLE_DEBUG @@ -63,17 +63,9 @@ t8_element_copy_surround (const p4est_quadrant_t *q, p4est_quadrant_t *r) void t8_default_scheme_quad_c::t8_element_copy (const t8_element_t *source, t8_element_t *dest) const { - const p4est_quadrant_t *q = (const p4est_quadrant_t *) source; - p4est_quadrant_t *r = (p4est_quadrant_t *) dest; - T8_ASSERT (t8_element_is_valid (source)); + t8_dquad_copy ((const p4est_quadrant_t *) source, (p4est_quadrant_t *) dest); T8_ASSERT (t8_element_is_valid (dest)); - if (r == q) { - /* Do nothing if they are already the same quadrant. */ - return; - } - *r = *q; - t8_element_copy_surround (q, r); } int @@ -94,25 +86,17 @@ t8_default_scheme_quad_c::t8_element_equal (const t8_element_t *elem1, const t8_ void t8_default_scheme_quad_c::t8_element_parent (const t8_element_t *elem, t8_element_t *parent) const { - const p4est_quadrant_t *q = (const p4est_quadrant_t *) elem; - p4est_quadrant_t *r = (p4est_quadrant_t *) parent; - T8_ASSERT (t8_element_is_valid (elem)); + t8_dquad_parent ((const p4est_quadrant_t *) elem, (p4est_quadrant_t *) parent); T8_ASSERT (t8_element_is_valid (parent)); - p4est_quadrant_parent (q, r); - t8_element_copy_surround (q, r); } void t8_default_scheme_quad_c::t8_element_sibling (const t8_element_t *elem, int sibid, t8_element_t *sibling) const { - const p4est_quadrant_t *q = (const p4est_quadrant_t *) elem; - p4est_quadrant_t *r = (p4est_quadrant_t *) sibling; - T8_ASSERT (t8_element_is_valid (elem)); + t8_dquad_sibling ((const p4est_quadrant_t *) elem, sibid, (p4est_quadrant_t *) sibling); T8_ASSERT (t8_element_is_valid (sibling)); - p4est_quadrant_sibling (q, r, sibid); - t8_element_copy_surround (q, r); } int @@ -172,24 +156,9 @@ t8_default_scheme_quad_c::t8_element_get_corner_face (const t8_element_t *elemen void t8_default_scheme_quad_c::t8_element_child (const t8_element_t *elem, int childid, t8_element_t *child) const { - const p4est_quadrant_t *q = (const p4est_quadrant_t *) elem; - const p4est_qcoord_t shift = P4EST_QUADRANT_LEN (q->level + 1); - p4est_quadrant_t *r = (p4est_quadrant_t *) child; - T8_ASSERT (t8_element_is_valid (elem)); + t8_dquad_child ((const p4est_quadrant_t *) elem, childid, (p4est_quadrant_t *) child); T8_ASSERT (t8_element_is_valid (child)); - T8_ASSERT (p4est_quadrant_is_extended (q)); - T8_ASSERT (q->level < P4EST_QMAXLEVEL); - T8_ASSERT (childid >= 0 && childid < P4EST_CHILDREN); - - r->x = childid & 0x01 ? (q->x | shift) : q->x; - r->y = childid & 0x02 ? (q->y | shift) : q->y; - r->level = q->level + 1; - - if (q != r) { - T8_ASSERT (p4est_quadrant_is_parent (q, r)); - } - t8_element_copy_surround (q, r); } void @@ -241,23 +210,55 @@ t8_default_scheme_quad_c::t8_element_is_family (t8_element_t *const *fam) const } void -t8_default_scheme_quad_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const +t8_default_scheme_quad_c::t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); - T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << P4EST_DIM * level); + if (!multilevel) { + T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << P4EST_DIM * level); + p4est_quadrant_set_morton ((p4est_quadrant_t *) elem, level, id); + } + else { +#ifdef T8_ENABLE_DEBUG + int id_max = 0; + for (int i_level = 0; i_level <= level; i_level++) { + id_max += ((t8_linearidx_t) 1) << P4EST_DIM * i_level; + } + T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << P4EST_DIM * id_max); +#endif + /* The multilevel conversion happens via the following formula: + * #\f$\mathrm{id_{multilevel}} (\mathrm{id_{linear}, lvl}) = \mathrm{lvl} + \sum_{n = 0}^{\mathrm{lvl_{max}-1}} \lfloor \mathrm{id_{linear}} / 2^{n \cdot d} \rfloor \f$ + */ + t8_linearidx_t id_linear = 0; + for (int i_level = 0; i_level < level; i_level++) { + id_linear |= ((id - level) & (1 << i_level)) << i_level; + } + p4est_quadrant_set_morton ((p4est_quadrant_t *) elem, level, id_linear); + } - p4est_quadrant_set_morton ((p4est_quadrant_t *) elem, level, id); T8_QUAD_SET_TDIM ((p4est_quadrant_t *) elem, 2); } t8_linearidx_t -t8_default_scheme_quad_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const +t8_default_scheme_quad_c::t8_element_get_linear_id (const t8_element_t *elem, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); - return p4est_quadrant_linear_id ((p4est_quadrant_t *) elem, level); + const t8_linearidx_t id = p4est_quadrant_linear_id ((p4est_quadrant_t *) elem, level); + + if (multilevel) { + int id_multilevel = level; + for (int i_level = 0; i_level < P4EST_QMAXLEVEL; i_level++) { + id_multilevel += id >> (i_level * 2); + } + return id_multilevel; + } + else { + return id; + } } void @@ -281,13 +282,13 @@ t8_default_scheme_quad_c::t8_element_last_descendant (const t8_element_t *elem, } void -t8_default_scheme_quad_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2) const +t8_default_scheme_quad_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem1)); - T8_ASSERT (t8_element_is_valid (elem2)); T8_ASSERT (0 <= t8_element_level (elem1) && t8_element_level (elem1) <= P4EST_QMAXLEVEL); - p4est_quadrant_successor ((p4est_quadrant_t *) elem1, (p4est_quadrant_t *) elem2); - t8_element_copy_surround ((const p4est_quadrant_t *) elem1, (p4est_quadrant_t *) elem2); + t8_dquad_successor ((const p4est_quadrant_t *) elem1, (p4est_quadrant_t *) elem2, level, multilevel); + T8_ASSERT (t8_element_is_valid (elem2)); } void @@ -700,7 +701,7 @@ t8_default_scheme_quad_c::t8_element_reference_coords (const t8_element_t *elem, const size_t num_coords, double *out_coords) const { T8_ASSERT (t8_element_is_valid (elem)); - t8_dquad_compute_reference_coords ((const t8_dquad_t *) elem, ref_coords, num_coords, out_coords); + t8_dquad_compute_reference_coords ((const p4est_quadrant_t *) elem, ref_coords, num_coords, out_coords); } void diff --git a/src/t8_schemes/t8_default/t8_default_quad/t8_default_quad_cxx.hxx b/src/t8_schemes/t8_default/t8_default_quad/t8_default_quad_cxx.hxx index 197b87897d..3ceb75e05b 100644 --- a/src/t8_schemes/t8_default/t8_default_quad/t8_default_quad_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_quad/t8_default_quad_cxx.hxx @@ -486,22 +486,25 @@ struct t8_default_scheme_quad_c: public t8_default_scheme_common_c /** Initialize the entries of an allocated element according to a * given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const; /** Compute the linear id of a given element in a hypothetical uniform * refinement of a given level. * \param [in] elem The element whose id we compute. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const; /** Compute the first descendant of a given element. * \param [in] elem The element whose descendant is computed. @@ -522,12 +525,13 @@ struct t8_default_scheme_quad_c: public t8_default_scheme_common_c t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; /** Construct the successor in a uniform refinement of a given element. - * \param [in] elem1 The element whose successor should be constructed. - * \param [in,out] elem2 The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. + * \param [in] elem The element whose successor should be constructed. + * \param [in,out] succ The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ virtual void - t8_element_successor (const t8_element_t *elem, t8_element_t *succ) const; + t8_element_successor (const t8_element_t *elem, t8_element_t *succ, const int level, const int multilevel = 0) const; /** Get the integer coordinates of the anchor node of an element. * The default scheme implements the Morton type SFCs. In these SFCs the diff --git a/src/t8_schemes/t8_default/t8_default_quad/t8_dquad.h b/src/t8_schemes/t8_default/t8_default_quad/t8_dquad.h index e994c57bed..ec2b619fa9 100644 --- a/src/t8_schemes/t8_default/t8_default_quad/t8_dquad.h +++ b/src/t8_schemes/t8_default/t8_default_quad/t8_dquad.h @@ -47,13 +47,4 @@ /** The length of a quad at a given level in integer coordinates. */ #define T8_DQUAD_LEN(l) (1 << (T8_DQUAD_MAXLEVEL - (l))) -typedef int32_t t8_dquad_coord_t; - -typedef struct t8_dquad -{ - int8_t level; - t8_dquad_coord_t x; /**< The x integer coordinate of the anchor node. */ - t8_dquad_coord_t y; /**< The y integer coordinate of the anchor node. */ -} t8_dquad_t; - #endif /* T8_DQUAD_H */ diff --git a/src/t8_schemes/t8_default/t8_default_quad/t8_dquad_bits.c b/src/t8_schemes/t8_default/t8_default_quad/t8_dquad_bits.c index ad6ca9f6b3..4ff468e38b 100644 --- a/src/t8_schemes/t8_default/t8_default_quad/t8_dquad_bits.c +++ b/src/t8_schemes/t8_default/t8_default_quad/t8_dquad_bits.c @@ -20,24 +20,122 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include #include +#include + +static void +t8_element_copy_surround (const p4est_quadrant_t *q, p4est_quadrant_t *r) +{ + T8_QUAD_SET_TDIM (r, T8_QUAD_GET_TDIM (q)); + if (T8_QUAD_GET_TDIM (q) == 3) { + T8_QUAD_SET_TNORMAL (r, T8_QUAD_GET_TNORMAL (q)); + T8_QUAD_SET_TCOORD (r, T8_QUAD_GET_TCOORD (q)); + } +} void -t8_dquad_compute_reference_coords (const t8_dquad_t *elem, const double *ref_coords, const size_t num_coords, +t8_dquad_compute_reference_coords (const p4est_quadrant_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords) { - const p4est_quadrant_t *q1 = (const p4est_quadrant_t *) elem; - - const p4est_qcoord_t h = P4EST_QUADRANT_LEN (q1->level); + const p4est_qcoord_t h = P4EST_QUADRANT_LEN (elem->level); for (size_t icoord = 0; icoord < num_coords; ++icoord) { const size_t offset_2d = icoord * 2; const size_t offset_3d = icoord * 3; - out_coords[offset_2d + 0] = q1->x + ref_coords[offset_3d + 0] * h; - out_coords[offset_2d + 1] = q1->y + ref_coords[offset_3d + 1] * h; + out_coords[offset_2d + 0] = elem->x + ref_coords[offset_3d + 0] * h; + out_coords[offset_2d + 1] = elem->y + ref_coords[offset_3d + 1] * h; out_coords[offset_2d + 0] /= (double) P4EST_ROOT_LEN; out_coords[offset_2d + 1] /= (double) P4EST_ROOT_LEN; } } + +void +t8_dquad_child (const p4est_quadrant_t *elem, int childid, p4est_quadrant_t *child) +{ + const p4est_qcoord_t shift = P4EST_QUADRANT_LEN (elem->level + 1); + + T8_ASSERT (p4est_quadrant_is_extended (elem)); + T8_ASSERT (elem->level < P4EST_QMAXLEVEL); + T8_ASSERT (childid >= 0 && childid < P4EST_CHILDREN); + + child->x = childid & 0x01 ? (elem->x | shift) : elem->x; + child->y = childid & 0x02 ? (elem->y | shift) : elem->y; + child->level = elem->level + 1; + + if (elem != child) { + T8_ASSERT (p4est_quadrant_is_parent (elem, child)); + } + t8_element_copy_surround (elem, child); +} + +void +t8_dquad_parent (const p4est_quadrant_t *elem, p4est_quadrant_t *parent) +{ + T8_ASSERT (p4est_quadrant_is_extended (elem)); + p4est_quadrant_parent (elem, parent); + t8_element_copy_surround (elem, parent); +} + +void +t8_dquad_sibling (const p4est_quadrant_t *elem, int sibid, p4est_quadrant_t *sibling) +{ + T8_ASSERT (p4est_quadrant_is_extended (elem)); + p4est_quadrant_sibling (elem, sibling, sibid); + t8_element_copy_surround (elem, sibling); +} + +void +t8_dquad_copy (const p4est_quadrant_t *source, p4est_quadrant_t *dest) +{ + T8_ASSERT (p4est_quadrant_is_extended (source)); + if (source == dest) { + /* Do nothing if they are already the same quadrant. */ + return; + } + *dest = *source; + t8_element_copy_surround (source, dest); +} + +void +t8_dquad_successor (const p4est_quadrant_t *elem, p4est_quadrant_t *succ, const int level, const int multilevel) +{ + T8_ASSERT (p4est_quadrant_is_extended (elem)); + T8_ASSERT (0 <= elem->level && succ->level <= P4EST_QMAXLEVEL); + T8_ASSERT (0 <= level && level <= P4EST_QMAXLEVEL); + T8_ASSERT (elem->level <= level); + /* If level not reached, construct child */ + if (elem->level < level) { + t8_dquad_child (elem, 0, succ); + } + else { + /* If level reached, construct sibling */ + const int num_siblings = 4; + int child_id = p4est_quadrant_child_id (elem); + T8_ASSERT (0 <= child_id && child_id < num_siblings); + if (child_id < num_siblings - 1) { + t8_dquad_sibling (elem, child_id + 1, succ); + } + else { + /* elem is last sibling, go up until elem is not last sibling */ + t8_dquad_parent (elem, succ); + child_id = p4est_quadrant_child_id (succ); + T8_ASSERT (0 <= child_id && child_id < num_siblings); + while (child_id == num_siblings - 1) { + t8_dquad_parent (succ, succ); + child_id = p4est_quadrant_child_id (succ); + T8_ASSERT (0 <= child_id && child_id < num_siblings); + } + /* Construct next sibling */ + t8_dquad_sibling (succ, child_id + 1, succ); + } + } + if (!multilevel) { + /* If not multilevel, traverse down the tree */ + while (succ->level < level) { + t8_dquad_child (succ, 0, succ); + } + } +} diff --git a/src/t8_schemes/t8_default/t8_default_quad/t8_dquad_bits.h b/src/t8_schemes/t8_default/t8_default_quad/t8_dquad_bits.h index 8320e586ac..b6d54a801c 100644 --- a/src/t8_schemes/t8_default/t8_default_quad/t8_dquad_bits.h +++ b/src/t8_schemes/t8_default/t8_default_quad/t8_dquad_bits.h @@ -43,9 +43,52 @@ T8_EXTERN_C_BEGIN (); * of the points on the quad. */ void -t8_dquad_compute_reference_coords (const t8_dquad_t *elem, const double *ref_coords, const size_t num_coords, +t8_dquad_compute_reference_coords (const p4est_quadrant_t *elem, const double *ref_coords, const size_t num_coords, double *out_coords); +/** Compute the childid-th child in Morton order of a quad. + * \param [in] elem Input quad. + * \param [in] childid The id of the child, in 0 - 3, in Morton order. + * \param [in,out] child Existing quad whose data will be filled with the data of elem's childid-th child. + */ +void +t8_dquad_child (const p4est_quadrant_t *elem, int childid, p4est_quadrant_t *child); + +/** Compute the parent of a quad. + * \param [in] elem Input quad. + * \param [in,out] parent Existing quad whose data will + * be filled with the data of elem's parent. + * \note \a elem may point to the same quad as \a parent. + */ +void +t8_dquad_parent (const p4est_quadrant_t *elem, p4est_quadrant_t *parent); + +/** Compute the sibid-th sibling in Morton order of a quad. + * \param [in] elem Input quad. + * \param [in] sibid The id of the sibling, in 0 - 3, in Morton order. + * \param [in,out] sibling Existing quad whose data will be filled with the data of elem's sibid-th sibling. + */ +void +t8_dquad_sibling (const p4est_quadrant_t *elem, int sibid, p4est_quadrant_t *sibling); + +/** Copy all values from one quad to another. + * \param [in] elem The quad to be copied. + * \param [in,out] dest Existing quad whose data will be filled with the data + * of \a elem. + */ +void +t8_dquad_copy (const p4est_quadrant_t *source, p4est_quadrant_t *dest); + +/** Computes the successor of a quad in a uniform grid of level \a level. + * \param [in] elem Quad whose id will be computed. + * \param [in,out] succ Existing quad whose data will be filled with the + * data of \a elem's successor on level \a level. + * \param [in] level Level of uniform grid to be considered. + * \param [in] multilevel If \a multilevel is 1, ancestors can also be successors. + */ +void +t8_dquad_successor (const p4est_quadrant_t *elem, p4est_quadrant_t *succ, const int level, const int multilevel); + T8_EXTERN_C_END (); #endif /* T8_DQUAD_BITS_H */ diff --git a/src/t8_schemes/t8_default/t8_default_tet/t8_default_tet_cxx.cxx b/src/t8_schemes/t8_default/t8_default_tet/t8_default_tet_cxx.cxx index 537f2e0ae4..b4fdf74593 100644 --- a/src/t8_schemes/t8_default/t8_default_tet/t8_default_tet_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_tet/t8_default_tet_cxx.cxx @@ -393,7 +393,8 @@ t8_default_scheme_tet_c::t8_element_face_neighbor_inside (const t8_element_t *el } void -t8_default_scheme_tet_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const +t8_default_scheme_tet_c::t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) const { T8_ASSERT (0 <= level && level <= T8_DTET_MAXLEVEL); T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << 3 * level); @@ -403,7 +404,8 @@ t8_default_scheme_tet_c::t8_element_set_linear_id (t8_element_t *elem, int level } t8_linearidx_t -t8_default_scheme_tet_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const +t8_default_scheme_tet_c::t8_element_get_linear_id (const t8_element_t *elem, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= T8_DTET_MAXLEVEL); @@ -412,13 +414,14 @@ t8_default_scheme_tet_c::t8_element_get_linear_id (const t8_element_t *elem, int } void -t8_default_scheme_tet_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2) const +t8_default_scheme_tet_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); T8_ASSERT (0 <= t8_element_level (elem1) && t8_element_level (elem1) <= T8_DTET_MAXLEVEL); - t8_dtet_successor ((const t8_default_tet_t *) elem1, (t8_default_tet_t *) elem2, t8_element_level (elem1)); + t8_dtet_successor ((const t8_default_tet_t *) elem1, (t8_default_tet_t *) elem2, level); } void diff --git a/src/t8_schemes/t8_default/t8_default_tet/t8_default_tet_cxx.hxx b/src/t8_schemes/t8_default/t8_default_tet/t8_default_tet_cxx.hxx index 578ef62a8a..c163cdd86d 100644 --- a/src/t8_schemes/t8_default/t8_default_tet/t8_default_tet_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_tet/t8_default_tet_cxx.hxx @@ -401,22 +401,26 @@ struct t8_default_scheme_tet_c: public t8_default_scheme_common_c virtual int t8_element_face_neighbor_inside (const t8_element_t *elem, t8_element_t *neigh, int face, int *neigh_face) const; - /** Initialize the entries of an allocated element according to a given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. + /** Initialize the entries of an allocated element according to a + * given linear id in a uniform refinement. + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const; /** Compute the linear id of a given element in a hypothetical uniform refinement of a given level. * \param [in] elem The element whose id we compute. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const; /** Compute the first descendant of a given element. * \param [in] elem The element whose descendant is computed. @@ -435,12 +439,13 @@ struct t8_default_scheme_tet_c: public t8_default_scheme_common_c t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; /** Construct the successor in a uniform refinement of a given element. - * \param [in] elem1 The element whose successor should be constructed. - * \param [in,out] elem2 The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. + * \param [in] elem The element whose successor should be constructed. + * \param [in,out] succ The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ virtual void - t8_element_successor (const t8_element_t *elem, t8_element_t *succ) const; + t8_element_successor (const t8_element_t *elem, t8_element_t *succ, const int level, const int multilevel) const; /** Get the integer coordinates of the anchor node of an element. The default scheme implements the Morton type SFCs. * In these SFCs the elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and L the maximum diff --git a/src/t8_schemes/t8_default/t8_default_tri/t8_default_tri_cxx.cxx b/src/t8_schemes/t8_default/t8_default_tri/t8_default_tri_cxx.cxx index debf22a350..d7a44de844 100644 --- a/src/t8_schemes/t8_default/t8_default_tri/t8_default_tri_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_tri/t8_default_tri_cxx.cxx @@ -410,7 +410,8 @@ t8_default_scheme_tri_c::t8_element_face_neighbor_inside (const t8_element_t *el } void -t8_default_scheme_tri_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const +t8_default_scheme_tri_c::t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= T8_DTRI_MAXLEVEL); @@ -420,7 +421,8 @@ t8_default_scheme_tri_c::t8_element_set_linear_id (t8_element_t *elem, int level } t8_linearidx_t -t8_default_scheme_tri_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const +t8_default_scheme_tri_c::t8_element_get_linear_id (const t8_element_t *elem, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= T8_DTRI_MAXLEVEL); @@ -447,13 +449,14 @@ t8_default_scheme_tri_c::t8_element_last_descendant (const t8_element_t *elem, t } void -t8_default_scheme_tri_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2) const +t8_default_scheme_tri_c::t8_element_successor (const t8_element_t *elem1, t8_element_t *elem2, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem1)); T8_ASSERT (t8_element_is_valid (elem2)); T8_ASSERT (0 <= t8_element_level (elem1) && t8_element_level (elem1) <= T8_DTRI_MAXLEVEL); - t8_dtri_successor ((const t8_dtri_t *) elem1, (t8_dtri_t *) elem2, t8_element_level (elem1)); + t8_dtri_successor ((const t8_dtri_t *) elem1, (t8_dtri_t *) elem2, level); } void diff --git a/src/t8_schemes/t8_default/t8_default_tri/t8_default_tri_cxx.hxx b/src/t8_schemes/t8_default/t8_default_tri/t8_default_tri_cxx.hxx index 16a6d0f65e..0c6a99e0df 100644 --- a/src/t8_schemes/t8_default/t8_default_tri/t8_default_tri_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_tri/t8_default_tri_cxx.hxx @@ -395,22 +395,26 @@ struct t8_default_scheme_tri_c: public t8_default_scheme_common_c virtual int t8_element_face_neighbor_inside (const t8_element_t *elem, t8_element_t *neigh, int face, int *neigh_face) const; - /** Initialize the entries of an allocated element according to a given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. + /** Initialize the entries of an allocated element according to a + * given linear id in a uniform refinement. + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const; /** Compute the linear id of a given element in a hypothetical uniform refinement of a given level. * \param [in] elem The element whose id we compute. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const; /** Compute the first descendant of a given element. * \param [in] elem The element whose descendant is computed. @@ -429,12 +433,13 @@ struct t8_default_scheme_tri_c: public t8_default_scheme_common_c t8_element_last_descendant (const t8_element_t *elem, t8_element_t *desc, int level) const; /** Construct the successor in a uniform refinement of a given element. - * \param [in] elem1 The element whose successor should be constructed. - * \param [in,out] elem2 The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. + * \param [in] elem The element whose successor should be constructed. + * \param [in,out] succ The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ virtual void - t8_element_successor (const t8_element_t *elem, t8_element_t *succ) const; + t8_element_successor (const t8_element_t *elem, t8_element_t *succ, const int level, const int multilevel) const; /** Get the integer coordinates of the anchor node of an element. The default scheme implements the Morton type SFCs. * In these SFCs the elements are positioned in a cube [0,1]^(dL) with dimension d (=0,1,2,3) and L the maximum diff --git a/src/t8_schemes/t8_default/t8_default_vertex/t8_default_vertex_cxx.cxx b/src/t8_schemes/t8_default/t8_default_vertex/t8_default_vertex_cxx.cxx index 66f04aa81e..9c451d78f0 100644 --- a/src/t8_schemes/t8_default/t8_default_vertex/t8_default_vertex_cxx.cxx +++ b/src/t8_schemes/t8_default/t8_default_vertex/t8_default_vertex_cxx.cxx @@ -195,7 +195,8 @@ t8_default_scheme_vertex_c::t8_element_is_root_boundary (const t8_element_t *ele } void -t8_default_scheme_vertex_c::t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const +t8_default_scheme_vertex_c::t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel) const { T8_ASSERT (0 <= level && level <= T8_DVERTEX_MAXLEVEL); T8_ASSERT (0 <= id && id < ((t8_linearidx_t) 1) << 3 * level); @@ -205,7 +206,8 @@ t8_default_scheme_vertex_c::t8_element_set_linear_id (t8_element_t *elem, int le } t8_linearidx_t -t8_default_scheme_vertex_c::t8_element_get_linear_id (const t8_element_t *elem, int level) const +t8_default_scheme_vertex_c::t8_element_get_linear_id (const t8_element_t *elem, const int level, + const int multilevel) const { T8_ASSERT (t8_element_is_valid (elem)); T8_ASSERT (0 <= level && level <= T8_DVERTEX_MAXLEVEL); diff --git a/src/t8_schemes/t8_default/t8_default_vertex/t8_default_vertex_cxx.hxx b/src/t8_schemes/t8_default/t8_default_vertex/t8_default_vertex_cxx.hxx index 8eccdf7b19..5a03f21348 100644 --- a/src/t8_schemes/t8_default/t8_default_vertex/t8_default_vertex_cxx.hxx +++ b/src/t8_schemes/t8_default/t8_default_vertex/t8_default_vertex_cxx.hxx @@ -488,22 +488,25 @@ struct t8_default_scheme_vertex_c: public t8_default_scheme_common_c /** Initialize the entries of an allocated element according to a * given linear id in a uniform refinement. - * \param [in,out] elem The element whose entries will be set. - * \param [in] level The level of the uniform refinement to consider. - * \param [in] id The linear id. + * \param [in,out] elem The element whose entries will be set. + * \param [in] level The level of the uniform refinement to consider. + * \param [in] id The linear id. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * id must fulfil 0 <= id < 'number of leaves in the uniform refinement' */ virtual void - t8_element_set_linear_id (t8_element_t *elem, int level, t8_linearidx_t id) const; + t8_element_set_linear_id (t8_element_t *elem, const int level, const t8_linearidx_t id, + const int multilevel = 0) const; /** Compute the linear id of a given element in a hypothetical uniform * refinement of a given level. * \param [in] elem The element whose id we compute. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Shifts the linear id to make space for multiple levels. * \return The linear id of the element. */ virtual t8_linearidx_t - t8_element_get_linear_id (const t8_element_t *elem, int level) const; + t8_element_get_linear_id (const t8_element_t *elem, const int level, const int multilevel) const; /** Compute the first descendant of a given element. * \param [in] elem The element whose descendant is computed. @@ -527,9 +530,10 @@ struct t8_default_scheme_vertex_c: public t8_default_scheme_common_c * \param [in] elem1 The element whose successor should be constructed. * \param [in,out] elem2 The element whose entries will be set. * \param [in] level The level of the uniform refinement to consider. + * \param [in] multilevel Consider ancestors as successors. */ virtual void - t8_element_successor (const t8_element_t *elem, t8_element_t *succ) const + t8_element_successor (const t8_element_t *elem, t8_element_t *succ, const int level, const int multilevel) const { SC_ABORT ("Not implemented.\n"); return; /* prevents compiler warning */ diff --git a/test/t8_cmesh/t8_gtest_cmesh_partition.cxx b/test/t8_cmesh/t8_gtest_cmesh_partition.cxx index b372256e56..15f010ee35 100644 --- a/test/t8_cmesh/t8_gtest_cmesh_partition.cxx +++ b/test/t8_cmesh/t8_gtest_cmesh_partition.cxx @@ -86,7 +86,7 @@ TEST_P (t8_cmesh_partition_class, test_cmesh_partition_concentrate) t8_cmesh_init (&cmesh_partition); t8_cmesh_set_derive (cmesh_partition, cmesh_original); /* Uniform partition according to level */ - t8_cmesh_set_partition_uniform (cmesh_partition, level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_partition, sc_MPI_COMM_WORLD); test_cmesh_committed (cmesh_partition); @@ -126,7 +126,7 @@ TEST_P (t8_cmesh_partition_class, test_cmesh_partition_concentrate) for (int i = 0; i < 2; i++) { t8_cmesh_init (&cmesh_partition_new2); t8_cmesh_set_derive (cmesh_partition_new2, cmesh_partition_new1); - t8_cmesh_set_partition_uniform (cmesh_partition_new2, level, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition_new2, level, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_partition_new2, sc_MPI_COMM_WORLD); cmesh_partition_new1 = cmesh_partition_new2; } diff --git a/test/t8_cmesh/t8_gtest_multiple_attributes.cxx b/test/t8_cmesh/t8_gtest_multiple_attributes.cxx index 17c66d9842..5c4229e87c 100644 --- a/test/t8_cmesh/t8_gtest_multiple_attributes.cxx +++ b/test/t8_cmesh/t8_gtest_multiple_attributes.cxx @@ -35,7 +35,7 @@ t8_cmesh_partition_cmesh (t8_cmesh_t cmesh, sc_MPI_Comm comm) t8_cmesh_t cmesh_partition; t8_cmesh_init (&cmesh_partition); t8_cmesh_set_derive (cmesh_partition, cmesh); - t8_cmesh_set_partition_uniform (cmesh_partition, 0, t8_scheme_new_default_cxx ()); + t8_cmesh_set_partition_uniform (cmesh_partition, 0, 0, t8_scheme_new_default_cxx ()); t8_cmesh_commit (cmesh_partition, comm); return cmesh_partition; } diff --git a/test/t8_forest/t8_gtest_balance.cxx b/test/t8_forest/t8_gtest_balance.cxx index 40c7d3ae9d..e04d4dc645 100644 --- a/test/t8_forest/t8_gtest_balance.cxx +++ b/test/t8_forest/t8_gtest_balance.cxx @@ -67,7 +67,7 @@ TEST_P (gtest_balance, confirm_is_balanced_check_for_uniform_forests) t8_scheme_cxx_t *default_scheme = t8_scheme_new_default_cxx (); t8_cmesh_t cmesh = t8_cmesh_new_hypercube (ieclass, sc_MPI_COMM_WORLD, 0, 0, ido_periodic); - t8_forest_t forest = t8_forest_new_uniform (cmesh, default_scheme, ilevel, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, default_scheme, ilevel, 0, 0, sc_MPI_COMM_WORLD); EXPECT_EQ (t8_forest_is_balanced (forest), 1); diff --git a/test/t8_forest/t8_gtest_element_volume.cxx b/test/t8_forest/t8_gtest_element_volume.cxx index f0710a99f5..1474cde9f5 100644 --- a/test/t8_forest/t8_gtest_element_volume.cxx +++ b/test/t8_forest/t8_gtest_element_volume.cxx @@ -47,7 +47,7 @@ class t8_forest_volume: public testing::TestWithParam (GetParam ()); scheme = t8_scheme_new_default_cxx (); t8_cmesh_t cmesh = t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 0, 0); - forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, scheme, level, 0, 0, sc_MPI_COMM_WORLD); } void TearDown () override diff --git a/test/t8_forest/t8_gtest_find_owner.cxx b/test/t8_forest/t8_gtest_find_owner.cxx index 59b3c5ffd9..73ec74b7ce 100644 --- a/test/t8_forest/t8_gtest_find_owner.cxx +++ b/test/t8_forest/t8_gtest_find_owner.cxx @@ -145,7 +145,7 @@ TEST_P (forest_find_owner, find_multiple_owners) /* initialize the array of owners to store ints */ sc_array_init (&owners, sizeof (int)); /* Build a uniform forest */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, default_scheme, level, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, default_scheme, level, 0, 0, sc_MPI_COMM_WORLD); t8_eclass_scheme_c *ts = t8_forest_get_eclass_scheme (forest, eclass); /* Construct the root element */ ts->t8_element_new (1, &root_element); diff --git a/test/t8_forest/t8_gtest_forest_commit.cxx b/test/t8_forest/t8_gtest_forest_commit.cxx index 2a91a67621..0423a506f5 100644 --- a/test/t8_forest/t8_gtest_forest_commit.cxx +++ b/test/t8_forest/t8_gtest_forest_commit.cxx @@ -149,7 +149,7 @@ TEST_P (forest_commit, test_forest_commit) /* ref the cmesh since we reuse it */ t8_cmesh_ref (cmesh); /* Create a uniformly refined forest */ - forest = t8_forest_new_uniform (cmesh, scheme, level, 1, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, scheme, level, 1, 0, sc_MPI_COMM_WORLD); /* We need to use forest twice, so we ref it */ t8_forest_ref (forest); /* Adapt, balance and partition the forest */ diff --git a/test/t8_forest/t8_gtest_forest_face_normal.cxx b/test/t8_forest/t8_gtest_forest_face_normal.cxx index 04c56c0eca..96ed532136 100644 --- a/test/t8_forest/t8_gtest_forest_face_normal.cxx +++ b/test/t8_forest/t8_gtest_forest_face_normal.cxx @@ -44,7 +44,7 @@ class class_forest_face_normal: public testing::TestWithParamt8_element_level (elements[0]); - t8_linearidx_t eid = ts->t8_element_get_linear_id (elements[0], level); + t8_linearidx_t eid = ts->t8_element_get_linear_id (elements[0], level, forest->multilevel); int maxlevel = *(int *) t8_forest_get_user_data (forest); if (eid % 2 && level < maxlevel) { @@ -132,7 +132,7 @@ TEST_P (forest_ghost_owner, test_ghost_owner) /* ref the cmesh since we reuse it */ t8_cmesh_ref (cmesh); /* Create a uniformly refined forest */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 1, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 1, 0, sc_MPI_COMM_WORLD); /* Check the owners of the ghost elements */ t8_test_gao_check (forest); /* Adapt the forest and exchange data again */ diff --git a/test/t8_forest/t8_gtest_ghost_delete.cxx b/test/t8_forest/t8_gtest_ghost_delete.cxx index 95d6626b93..150a91f5f3 100644 --- a/test/t8_forest/t8_gtest_ghost_delete.cxx +++ b/test/t8_forest/t8_gtest_ghost_delete.cxx @@ -112,7 +112,7 @@ TEST_F (DISABLED_forest_ghost_exchange_holes, errorTest) const int execute_ghost = 1; t8_cmesh_ref (cmesh); t8_scheme_cxx_ref (scheme); - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 1, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 1, 0, comm); forest = t8_forest_new_adapt (forest, test_adapt_holes, 0, execute_ghost, NULL); forest = t8_forest_new_adapt (forest, test_adapt_holes, 0, execute_ghost, NULL); t8_forest_unref (&forest); diff --git a/test/t8_forest/t8_gtest_ghost_exchange.cxx b/test/t8_forest/t8_gtest_ghost_exchange.cxx index 0ccdeb8c04..a572411595 100644 --- a/test/t8_forest/t8_gtest_ghost_exchange.cxx +++ b/test/t8_forest/t8_gtest_ghost_exchange.cxx @@ -72,7 +72,7 @@ t8_test_exchange_adapt (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t { /* refine every second element up to the maximum level */ int level = ts->t8_element_level (elements[0]); - t8_linearidx_t eid = ts->t8_element_get_linear_id (elements[0], level); + t8_linearidx_t eid = ts->t8_element_get_linear_id (elements[0], level, forest->multilevel); int maxlevel = *(int *) t8_forest_get_user_data (forest); if (eid % 2 && level < maxlevel) { @@ -105,7 +105,7 @@ t8_test_ghost_exchange_data_id (t8_forest_t forest) /* Get a pointer to this element */ const t8_element_t *elem = t8_forest_get_element_in_tree (forest, itree, ielem); /* Compute the linear id of this element */ - t8_linearidx_t elem_id = ts->t8_element_get_linear_id (elem, ts->t8_element_level (elem)); + t8_linearidx_t elem_id = ts->t8_element_get_linear_id (elem, ts->t8_element_level (elem), forest->multilevel); /* Store this id at the element's index in the array */ *(t8_linearidx_t *) sc_array_index (&element_data, array_pos) = elem_id; array_pos++; @@ -124,7 +124,7 @@ t8_test_ghost_exchange_data_id (t8_forest_t forest) /* Get a pointer to this ghost */ const t8_element_t *elem = t8_forest_ghost_get_element (forest, itree, ielem); /* Compute its ghost_id */ - t8_linearidx_t ghost_id = ts->t8_element_get_linear_id (elem, ts->t8_element_level (elem)); + t8_linearidx_t ghost_id = ts->t8_element_get_linear_id (elem, ts->t8_element_level (elem), forest->multilevel); /* Compare this id with the entry in the element_data array */ t8_linearidx_t ghost_entry = *(t8_linearidx_t *) sc_array_index (&element_data, array_pos); ASSERT_EQ (ghost_id, ghost_entry) << "Error when exchanging ghost data. Received wrong element id.\n"; @@ -181,7 +181,7 @@ TEST_P (forest_ghost_exchange, test_ghost_exchange) /* ref the cmesh since we reuse it */ t8_cmesh_ref (cmesh); /* Create a uniformly refined forest */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 1, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 1, 0, sc_MPI_COMM_WORLD); /* exchange ghost data */ t8_test_ghost_exchange_data_int (forest); t8_test_ghost_exchange_data_id (forest); diff --git a/test/t8_forest/t8_gtest_half_neighbors.cxx b/test/t8_forest/t8_gtest_half_neighbors.cxx index ae85337c3e..e5901a58e9 100644 --- a/test/t8_forest/t8_gtest_half_neighbors.cxx +++ b/test/t8_forest/t8_gtest_half_neighbors.cxx @@ -89,7 +89,7 @@ TEST_P (forest_half_neighbors, test_half_neighbors) /* initialize the array of owners to store ints */ sc_array_init (&owners, sizeof (int)); /* Build a uniform forest */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, default_scheme, level, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, default_scheme, level, 0, 0, sc_MPI_COMM_WORLD); t8_eclass_scheme_c *ts = t8_forest_get_eclass_scheme (forest, eclass); /* iterate over all elements */ for (t8_locidx_t itree = 0; itree < t8_forest_get_num_local_trees (forest); itree++) { diff --git a/test/t8_forest/t8_gtest_search.cxx b/test/t8_forest/t8_gtest_search.cxx index 7b0f52620c..e77e8156e9 100644 --- a/test/t8_forest/t8_gtest_search.cxx +++ b/test/t8_forest/t8_gtest_search.cxx @@ -42,7 +42,7 @@ class forest_search: public testing::TestWithParam> { /* Construct a cube coarse mesh */ cmesh = t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 0, 0); /* Build a uniform forest */ - forest = t8_forest_new_uniform (cmesh, default_scheme, level, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, default_scheme, level, 0, 0, sc_MPI_COMM_WORLD); } void TearDown () override diff --git a/test/t8_forest/t8_gtest_user_data.cxx b/test/t8_forest/t8_gtest_user_data.cxx index bd54fddc30..5d7e3c65e7 100644 --- a/test/t8_forest/t8_gtest_user_data.cxx +++ b/test/t8_forest/t8_gtest_user_data.cxx @@ -39,7 +39,7 @@ TEST (user_data, test_user_data) /* Build a forest */ t8_cmesh_t cmesh = t8_cmesh_new_hypercube (T8_ECLASS_TRIANGLE, sc_MPI_COMM_WORLD, 0, 0, 0); t8_scheme_cxx_t *scheme = t8_scheme_new_default_cxx (); - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, 1, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, 1, 0, 0, sc_MPI_COMM_WORLD); /* Define user data */ double data = 42.42; double *get_data; @@ -97,7 +97,7 @@ TEST (user_data, test_user_function) /* Build a forest */ t8_cmesh_t cmesh = t8_cmesh_new_hypercube (T8_ECLASS_TRIANGLE, sc_MPI_COMM_WORLD, 0, 0, 0); t8_scheme_cxx_t *scheme = t8_scheme_new_default_cxx (); - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, 1, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, 1, 0, 0, sc_MPI_COMM_WORLD); double (*funpointer) (int); void (*funpointer_second) (void); diff --git a/test/t8_forest_incomplete/t8_gtest_empty_global_tree.cxx b/test/t8_forest_incomplete/t8_gtest_empty_global_tree.cxx index bcae9e44e5..b4b23784eb 100644 --- a/test/t8_forest_incomplete/t8_gtest_empty_global_tree.cxx +++ b/test/t8_forest_incomplete/t8_gtest_empty_global_tree.cxx @@ -46,7 +46,7 @@ class DISABLED_global_tree: public testing::TestWithParam (GetParam ()); testcase = std::get<1> (GetParam ()); forest = t8_forest_new_uniform (t8_cmesh_new_bigmesh (eclass, 3, sc_MPI_COMM_WORLD), t8_scheme_new_default_cxx (), - 0, 0, sc_MPI_COMM_WORLD); + 0, 0, 0, sc_MPI_COMM_WORLD); } void TearDown () override diff --git a/test/t8_forest_incomplete/t8_gtest_empty_local_tree.cxx b/test/t8_forest_incomplete/t8_gtest_empty_local_tree.cxx index e57d6fe1ec..f42cd71d4c 100644 --- a/test/t8_forest_incomplete/t8_gtest_empty_local_tree.cxx +++ b/test/t8_forest_incomplete/t8_gtest_empty_local_tree.cxx @@ -63,7 +63,7 @@ class local_tree: public testing::TestWithParam { sc_MPI_Comm_size (sc_MPI_COMM_WORLD, &MPI_size); forest = t8_forest_new_uniform (t8_cmesh_new_from_class (eclass, sc_MPI_COMM_WORLD), t8_scheme_new_default_cxx (), - MPI_size, 0, sc_MPI_COMM_WORLD); + MPI_size, 0, 0, sc_MPI_COMM_WORLD); if (MPI_size == 1 || MPI_size > MAX_NUM_RANKS) { GTEST_SKIP (); diff --git a/test/t8_forest_incomplete/t8_gtest_iterate_replace.cxx b/test/t8_forest_incomplete/t8_gtest_iterate_replace.cxx index 42a1cc651d..c5095259f6 100644 --- a/test/t8_forest_incomplete/t8_gtest_iterate_replace.cxx +++ b/test/t8_forest_incomplete/t8_gtest_iterate_replace.cxx @@ -45,7 +45,7 @@ class forest_iterate: public testing::TestWithParam { /* empty cmeshes are currently not supported */ GTEST_SKIP (); } - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 4, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 4, 0, 0, sc_MPI_COMM_WORLD); } void TearDown () override diff --git a/test/t8_forest_incomplete/t8_gtest_permute_hole.cxx b/test/t8_forest_incomplete/t8_gtest_permute_hole.cxx index 162d747d5f..7cb0b69aa7 100644 --- a/test/t8_forest_incomplete/t8_gtest_permute_hole.cxx +++ b/test/t8_forest_incomplete/t8_gtest_permute_hole.cxx @@ -71,7 +71,7 @@ class forest_permute: public testing::TestWithParam { level = eclass < 4 ? 2 : 1; #endif forest = t8_forest_new_uniform (t8_cmesh_new_from_class (eclass, sc_MPI_COMM_WORLD), t8_scheme_new_default_cxx (), - level, 0, sc_MPI_COMM_WORLD); + level, 0, 0, sc_MPI_COMM_WORLD); sc_MPI_Comm_size (sc_MPI_COMM_WORLD, &MPI_size); if (MPI_size > 1) { diff --git a/test/t8_forest_incomplete/t8_gtest_recursive.cxx b/test/t8_forest_incomplete/t8_gtest_recursive.cxx index 62e9f469d1..54d2c2eeb2 100644 --- a/test/t8_forest_incomplete/t8_gtest_recursive.cxx +++ b/test/t8_forest_incomplete/t8_gtest_recursive.cxx @@ -53,9 +53,9 @@ class recursive_tree: public testing::TestWithParam { t8_cmesh_ref (cmesh); /* The forest to be adapted. */ - forest = t8_forest_new_uniform (cmesh, scheme, 1, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, scheme, 1, 0, 0, sc_MPI_COMM_WORLD); /* The forest contains only root elements and serves as a comparison. */ - forest_base = t8_forest_new_uniform (cmesh, scheme, 0, 0, sc_MPI_COMM_WORLD); + forest_base = t8_forest_new_uniform (cmesh, scheme, 0, 0, 0, sc_MPI_COMM_WORLD); } void TearDown () override diff --git a/test/t8_geometry/t8_gtest_point_inside.cxx b/test/t8_geometry/t8_gtest_point_inside.cxx index 5cf5bbe687..ca89f7dab5 100644 --- a/test/t8_geometry/t8_gtest_point_inside.cxx +++ b/test/t8_geometry/t8_gtest_point_inside.cxx @@ -60,7 +60,7 @@ TEST (t8_point_inside, test_point_inside_specific_triangle) /* We use standard linear geometry */ t8_cmesh_register_geometry (cmesh, 2); t8_cmesh_commit (cmesh, sc_MPI_COMM_WORLD); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 0, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 0, 0, 0, sc_MPI_COMM_WORLD); if (t8_forest_get_local_num_elements (forest) <= 0) { /* Skip empty forests (can occur when executed in parallel) */ @@ -101,7 +101,7 @@ TEST (t8_point_inside, test_point_inside_specific_quad) /* We use standard linear geometry */ t8_cmesh_register_geometry (cmesh, 2); t8_cmesh_commit (cmesh, sc_MPI_COMM_WORLD); - t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 0, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 0, 0, 0, sc_MPI_COMM_WORLD); if (t8_forest_get_local_num_elements (forest) <= 0) { /* Skip empty forests (can occur when executed in parallel) */ @@ -197,7 +197,7 @@ TEST_P (geometry_point_inside, test_point_inside) } /* Build a uniform forest */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, default_scheme, level, 1, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, default_scheme, level, 1, 0, sc_MPI_COMM_WORLD); const t8_locidx_t num_trees = t8_forest_get_num_local_trees (forest); for (t8_locidx_t itree = 0; itree < num_trees; ++itree) { diff --git a/test/t8_schemes/t8_gtest_element_ref_coords.cxx b/test/t8_schemes/t8_gtest_element_ref_coords.cxx index 880d29e4c5..57feb3fa42 100644 --- a/test/t8_schemes/t8_gtest_element_ref_coords.cxx +++ b/test/t8_schemes/t8_gtest_element_ref_coords.cxx @@ -230,7 +230,7 @@ class class_ref_coords: public testing::TestWithParam (params); const int level = std::get<1> (params); t8_cmesh_t cmesh = t8_cmesh_new_from_class (eclass, sc_MPI_COMM_WORLD); - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, sc_MPI_COMM_WORLD); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, 0, sc_MPI_COMM_WORLD); t8_forest_init (&forest_partition); t8_forest_set_partition (forest_partition, forest, 0); t8_forest_commit (forest_partition); diff --git a/test/t8_schemes/t8_gtest_init_linear_id.cxx b/test/t8_schemes/t8_gtest_init_linear_id.cxx index 6b113c8d3c..414469d0a6 100644 --- a/test/t8_schemes/t8_gtest_init_linear_id.cxx +++ b/test/t8_schemes/t8_gtest_init_linear_id.cxx @@ -22,6 +22,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +#include #include #include #include @@ -79,7 +80,7 @@ TEST_P (linear_id, uniform_forest) /* Construct a forest with a single element of the current class*/ cmesh = t8_cmesh_new_from_class (ts->eclass, comm); t8_cmesh_ref (cmesh); - forest = t8_forest_new_uniform (cmesh, scheme, 0, 0, comm); + forest = t8_forest_new_uniform (cmesh, scheme, 0, 0, 0, comm); t8_scheme_cxx_ref (scheme); for (int level = 0; level < maxlvl; level++) { /*Get the number of local trees*/ @@ -97,7 +98,7 @@ TEST_P (linear_id, uniform_forest) /*Get the current element*/ const t8_element_t *element = t8_forest_get_element_in_tree (forest, tree_id, id_iter); /*Get the ID of the element at current level */ - const t8_locidx_t id = ts->t8_element_get_linear_id (element, level); + const t8_locidx_t id = ts->t8_element_get_linear_id (element, level, forest->multilevel); /* Check the computed id*/ EXPECT_EQ (id, id_iter + shift); } @@ -131,7 +132,7 @@ TEST_P (linear_id, id_at_other_level) /* Set the child at the current level */ ts->t8_element_set_linear_id (child, level, id); /* Compute the id of child at a higher level. */ - const t8_linearidx_t id_at_lvl = ts->t8_element_get_linear_id (child, level + add_lvl); + const t8_linearidx_t id_at_lvl = ts->t8_element_get_linear_id (child, level + add_lvl, 0); /* Compute how many leaves/descendants child has at level level+add_lvl */ const t8_linearidx_t child_desc = ts->t8_element_count_leaves (child, level + add_lvl); /* Iterate over all descendants */ @@ -140,7 +141,7 @@ TEST_P (linear_id, id_at_other_level) * leaf_id into the region of the descendants of child*/ ts->t8_element_set_linear_id (test, level + add_lvl, id_at_lvl + leaf_id); /* Compute the id of the descendant (test) at the current level */ - const t8_linearidx_t test_id = ts->t8_element_get_linear_id (test, level); + const t8_linearidx_t test_id = ts->t8_element_get_linear_id (test, level, 0); /* test_id and id should be equal. */ EXPECT_EQ (id, test_id); } diff --git a/test/t8_schemes/t8_gtest_nca.cxx b/test/t8_schemes/t8_gtest_nca.cxx index 6a301ee4c0..252214be4b 100644 --- a/test/t8_schemes/t8_gtest_nca.cxx +++ b/test/t8_schemes/t8_gtest_nca.cxx @@ -189,18 +189,18 @@ t8_recursive_nca_check (t8_element_t *check_nca, t8_element_t *desc_a, t8_elemen * This makes debugging a lot easier, as one can reconstruct the descendants * via t8_element_set_linear_id and can directly test them instead of waiting * until the recursion reaches the faulty computation. */ - t8_debugf ("id of desc_a: %li, level: %i\n", ts->t8_element_get_linear_id (desc_a, level_a), level_a); - t8_debugf ("id of desc_b: %li, level: %i\n", ts->t8_element_get_linear_id (desc_b, level_b), level_b); + t8_debugf ("id of desc_a: %li, level: %i\n", ts->t8_element_get_linear_id (desc_a, level_a, 0), level_a); + t8_debugf ("id of desc_b: %li, level: %i\n", ts->t8_element_get_linear_id (desc_b, level_b, 0), level_b); for (int k = SC_MAX (level_a, level_b); k >= 0; k--) { - t8_debugf ("id of desc_a: %li, level: %i\n", ts->t8_element_get_linear_id (desc_a, k), k); - t8_debugf ("id of desc_b: %li, level: %i\n", ts->t8_element_get_linear_id (desc_b, k), k); + t8_debugf ("id of desc_a: %li, level: %i\n", ts->t8_element_get_linear_id (desc_a, k, 0), k); + t8_debugf ("id of desc_b: %li, level: %i\n", ts->t8_element_get_linear_id (desc_b, k, 0), k); } - t8_debugf ("id of the correct nca: %li, level: %i\n", ts->t8_element_get_linear_id (check_nca, level_c), + t8_debugf ("id of the correct nca: %li, level: %i\n", ts->t8_element_get_linear_id (check_nca, level_c, 0), level_c); - t8_debugf ("id of the computed nca: %li, level: %i\n", ts->t8_element_get_linear_id (check, level_nca), + t8_debugf ("id of the computed nca: %li, level: %i\n", ts->t8_element_get_linear_id (check, level_nca, 0), level_nca); SC_ABORT ("Computed nca is not the correct nca!\n"); diff --git a/test/t8_schemes/t8_gtest_successor.cxx b/test/t8_schemes/t8_gtest_successor.cxx index ec13e864a7..1b2c5fc304 100644 --- a/test/t8_schemes/t8_gtest_successor.cxx +++ b/test/t8_schemes/t8_gtest_successor.cxx @@ -85,7 +85,7 @@ t8_recursive_successor (t8_element_t *element, t8_element_t *successor, t8_eleme /*Check if the successor in this element is computed correctly */ for (int ichild = 1; ichild < num_children; ichild++) { EXPECT_EQ (ts->t8_element_level (child), maxlvl); - ts->t8_element_successor (child, successor); + ts->t8_element_successor (child, successor, ts->t8_element_level (child), 0); ts->t8_element_child (element, ichild, child); EXPECT_ELEM_EQ (ts, child, successor); } @@ -96,7 +96,7 @@ t8_recursive_successor (t8_element_t *element, t8_element_t *successor, t8_eleme /*Compute the next successor / "jump" out of the current element */ else { EXPECT_EQ (ts->t8_element_level (child), maxlvl); - ts->t8_element_successor (child, successor); + ts->t8_element_successor (child, successor, ts->t8_element_level (child), 0); } } else { @@ -129,7 +129,7 @@ t8_deep_successor (t8_element_t *element, t8_element_t *successor, t8_element_t ASSERT_TRUE (ts->t8_element_equal (element, successor)) << "Wrong Successor at Maxlvl.\n"; /* Compute the next successor. */ EXPECT_EQ (ts->t8_element_level (successor), maxlvl); - ts->t8_element_successor (successor, successor); + ts->t8_element_successor (successor, successor, ts->t8_element_level (successor), 0); } ts->t8_element_parent (child, element); } diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 9d291eb3d3..85138080d0 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -21,4 +21,5 @@ add_t8_tutorial( NAME t8_step6_stencil SOURCES general/t8_step6 add_t8_tutorial( NAME t8_step7_interpolation SOURCES general/t8_step7_main.cxx general/t8_step7_interpolation.cxx ) add_t8_tutorial( NAME t8_tutorial_build_cmesh SOURCES general/t8_tutorial_build_cmesh.cxx general/t8_tutorial_build_cmesh_main.cxx) add_t8_tutorial( NAME t8_tutorial_search SOURCES general/t8_tutorial_search.cxx general/t8_step3_adapt_forest.cxx ) -add_t8_tutorial( NAME t8_features_curved_meshes SOURCES features/t8_features_curved_meshes.cxx) \ No newline at end of file +add_t8_tutorial( NAME t8_features_curved_meshes SOURCES features/t8_features_curved_meshes.cxx) +add_t8_tutorial( NAME t8_features_multilevel SOURCES features/t8_features_multilevel.cxx) \ No newline at end of file diff --git a/tutorials/Makefile.am b/tutorials/Makefile.am index 53abd1b8c7..1ff7eb12d4 100644 --- a/tutorials/Makefile.am +++ b/tutorials/Makefile.am @@ -14,7 +14,8 @@ bin_PROGRAMS += \ tutorials/general/t8_step7_interpolation \ tutorials/general/t8_tutorial_build_cmesh \ tutorials/general/t8_tutorial_search \ - tutorials/features/t8_features_curved_meshes + tutorials/features/t8_features_curved_meshes \ + tutorials/features/t8_features_multilevel dist_t8data_DATA += \ tutorials/features/t8_features_curved_meshes_generate_cmesh_hex.geo \ @@ -59,6 +60,8 @@ tutorials_general_t8_tutorial_search_SOURCES = \ tutorials/general/t8_step3_adapt_forest.cxx tutorials_features_t8_features_curved_meshes_SOURCES = \ tutorials/features/t8_features_curved_meshes.cxx +tutorials_features_t8_features_multilevel_SOURCES = \ + tutorials/features/t8_features_multilevel.cxx libt8_installed_headers += \ tutorials/general/t8_step3.h \ diff --git a/tutorials/features/t8_features_curved_meshes.cxx b/tutorials/features/t8_features_curved_meshes.cxx index acd428ef0e..aa694dc77d 100644 --- a/tutorials/features/t8_features_curved_meshes.cxx +++ b/tutorials/features/t8_features_curved_meshes.cxx @@ -439,7 +439,7 @@ main (int argc, char **argv) /* Read in the naca mesh from the msh file and the naca geometry from the brep file */ cmesh = t8_cmesh_from_msh_file (fp.c_str (), 0, sc_MPI_COMM_WORLD, dim, 0, cad || geometry); /* Construct a forest from the cmesh */ - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, comm); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, 0, comm); T8_ASSERT (t8_forest_is_committed (forest)); if (geometry) { t8_naca_geometry_refinement (forest, fp, level, rlevel_dorsal, rlevel_ventral, dim); diff --git a/tutorials/features/t8_features_multilevel.cxx b/tutorials/features/t8_features_multilevel.cxx new file mode 100644 index 0000000000..d8c4dc03c0 --- /dev/null +++ b/tutorials/features/t8_features_multilevel.cxx @@ -0,0 +1,171 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element types in parallel. + + Copyright (C) 2024 the developers + + t8code is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + t8code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* See also: https://github.com/holke/t8code/wiki/Step-4---Partition,-Balance,-Ghost + * + * This is step4 of the t8code tutorials. + * After generating a coarse mesh (step1), building a uniform forest + * on it (step2) and adapting this forest (step3) + * we will now lear how to control the forest creation in more detail, + * how to partition and balance a forest and how to generate a layer of ghost elements. + * + */ + +#include /* General t8code header, always include this. */ +#include /* cmesh definition and basic interface. */ +#include /* A collection of exemplary cmeshes */ +#include /* forest definition and basic interface. */ +#include /* save forest */ +#include /* default refinement scheme. */ +#include + +/* So far we have seen t8_forest_new_* functions to create forests. + * These directly returned a new forest. + * However, t8code offers us more control over the creation of forests. + * For example we can control whether or not a forest should have a ghost layer, + * be balanced/partitioned from another forest, etc. + * + * Usually, there are three steps involved in creating a forest: + * 1. Initialize the forest with t8_forest_init. + * This function will prepare a forest by setting default values for its members and + * initializing necessary structures. + * 2. Set all properties that the forest should have. + * Here we can for example set a cmesh and refinement scheme or specify that the + * forest should be adapted/partitioned/balanced from another forest etc. + * See the t8_forest_set functions in t8_forest.h + * The order in which you call the set functions does not matter. + * 3. Commit the forest with t8_forest_commit. + * In this step the forest is actually created after setting all + * desired properties. The forest cannot be changed after it was committed. + * + * The t8_forest_new functions are just wrappers around this process. + */ + +int +main (int argc, char **argv) +{ + int mpiret; + sc_MPI_Comm comm; + t8_cmesh_t cmesh; + t8_forest_t forest; + /* The prefix for our output files. */ + const char *prefix_uniform = "t8_multilevel_uniform_forest"; + const char *prefix_partition = "t8_multilevel_partitioned_forest"; + /* The uniform refinement level of the forest. */ + const int level = 3; + + /* Initialize MPI. This has to happen before we initialize sc or t8code. */ + mpiret = sc_MPI_Init (&argc, &argv); + /* Error check the MPI return value. */ + SC_CHECK_MPI (mpiret); + + /* Initialize the sc library, has to happen before we initialize t8code. */ + sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_ESSENTIAL); + /* Initialize t8code with log level SC_LP_PRODUCTION. See sc.h for more info on the log levels. */ + t8_init (SC_LP_DEBUG); + + /* Print a message on the root process. */ + t8_global_productionf (" [feature multilevel] \n"); + t8_global_productionf (" [feature multilevel] Hello, this is the multilevel example of t8code.\n"); + t8_global_productionf ( + " [feature multilevel] In this example we will explain the multilevel forest creation in more detail.\n"); + t8_global_productionf (" [feature multilevel] We will create a uniform multilevel forest and partition it.\n"); + t8_global_productionf (" [feature multilevel] \n"); + + /* We will use MPI_COMM_WORLD as a communicator. */ + comm = sc_MPI_COMM_WORLD; + + /* + * Setup. + * Build cmesh and uniform forest. + */ + + t8_global_productionf (" [feature multilevel] \n"); + t8_global_productionf (" [feature multilevel] Creating a uniform multilevel forest.\n"); + t8_global_productionf (" [feature multilevel] \n"); + /* Build a cube cmesh with one hex. */ + cmesh = t8_cmesh_new_hypercube (T8_ECLASS_QUAD, comm, 0, 0, 0); + t8_global_productionf (" [feature multilevel] Created coarse mesh.\n"); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, 1, comm); + + /* Print information of the forest. */ + //t8_step3_print_forest_information (forest); + + /* Write forest to vtu files. */ + t8_forest_write_vtk (forest, prefix_uniform); + t8_global_productionf (" [feature multilevel] Wrote uniform level %i forest to vtu files: %s*\n", level, + prefix_uniform); + + /* + * Partition the forest. + */ + + t8_global_productionf (" [feature multilevel] \n"); + t8_global_productionf (" [feature multilevel] Repartitioning the forest .\n"); + t8_global_productionf (" [feature multilevel] \n"); + t8_forest_t new_forest; + + /* Check that forest is a committed, that is valid and usable, forest. */ + T8_ASSERT (t8_forest_is_committed (forest)); + + /* Initialize */ + //t8_forest_init (&new_forest); + + /* Tell the new_forest that is should partition the existing forest. + * This will change the distribution of the forest elements among the processes + * in such a way that afterwards each process has the same number of elements + * (+- 1 if the number of elements is not divisible by the number of processes). + * + * The third 0 argument is the flag 'partition_for_coarsening' which is currently not + * implemented. Once it is, this will ensure that a family of elements will not be split + * across multiple processes and thus one level coarsening is always possible (see also the + * comments on coarsening in t8_step3). + */ + //t8_forest_set_partition (new_forest, forest, 0); + /* Tell the new_forest to create a ghost layer. + * This will gather those face neighbor elements of process local element that reside + * on a different process. + * + * We currently support ghost mode T8_GHOST_FACES that creates face neighbor ghost elements + * and will in future also support other modes for edge/vertex neighbor ghost elements. + */ + //t8_forest_commit (new_forest); + //t8_global_productionf (" [feature multilevel] Repartitioned forest.\n"); + //t8_step3_print_forest_information (forest); + /* Write forest to vtu files. */ + //t8_forest_write_vtk_ext (forest, prefix_partition, 1, 1, 1, 1, 0, 0, 1, 0, NULL); + + /* + * clean-up + */ + + /* Destroy the forest. */ + t8_forest_unref (&forest); + t8_global_productionf (" [feature multilevel] Destroyed forest.\n"); + + sc_finalize (); + + mpiret = sc_MPI_Finalize (); + SC_CHECK_MPI (mpiret); + + return 0; +} diff --git a/tutorials/general/t8_step2_uniform_forest.cxx b/tutorials/general/t8_step2_uniform_forest.cxx index d91a8ffbb8..ad9d03a506 100644 --- a/tutorials/general/t8_step2_uniform_forest.cxx +++ b/tutorials/general/t8_step2_uniform_forest.cxx @@ -85,7 +85,7 @@ t8_step2_build_uniform_forest (sc_MPI_Comm comm, t8_cmesh_t cmesh, int level) /* Create the refinement scheme. */ scheme = t8_scheme_new_default_cxx (); /* Creat the uniform forest. */ - forest = t8_forest_new_uniform (cmesh, scheme, level, 0, comm); + forest = t8_forest_new_uniform (cmesh, scheme, level, 0, 0, comm); return forest; } diff --git a/tutorials/general/t8_step3_adapt_forest.cxx b/tutorials/general/t8_step3_adapt_forest.cxx index 80fcdb4339..fe3bda8d1b 100644 --- a/tutorials/general/t8_step3_adapt_forest.cxx +++ b/tutorials/general/t8_step3_adapt_forest.cxx @@ -211,7 +211,7 @@ t8_step3_main (int argc, char **argv) /* Build a cube cmesh with tet, hex, and prism trees. */ cmesh = t8_cmesh_new_hypercube_hybrid (comm, 0, 0); t8_global_productionf (" [step3] Created coarse mesh.\n"); - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, comm); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, 0, comm); /* Print information of the forest. */ t8_global_productionf (" [step3] Created uniform forest.\n"); diff --git a/tutorials/general/t8_step4_partition_balance_ghost.cxx b/tutorials/general/t8_step4_partition_balance_ghost.cxx index ab388f253a..cf267f3cea 100644 --- a/tutorials/general/t8_step4_partition_balance_ghost.cxx +++ b/tutorials/general/t8_step4_partition_balance_ghost.cxx @@ -232,7 +232,7 @@ t8_step4_main (int argc, char **argv) /* Build a cube cmesh with tet, hex, and prism trees. */ cmesh = t8_cmesh_new_hypercube_hybrid (comm, 0, 0); t8_global_productionf (" [step4] Created coarse mesh.\n"); - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, comm); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, 1, comm); /* Print information of the forest. */ t8_step3_print_forest_information (forest); diff --git a/tutorials/general/t8_step5_element_data.cxx b/tutorials/general/t8_step5_element_data.cxx index 54867dd06b..c14e648748 100644 --- a/tutorials/general/t8_step5_element_data.cxx +++ b/tutorials/general/t8_step5_element_data.cxx @@ -72,7 +72,7 @@ t8_step5_build_forest (sc_MPI_Comm comm, int level) 0.4 /* Coarsen if outside this radius. */ }; /* Start with a uniform forest. */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, 0, comm); t8_forest_t forest_apbg; /* Adapt, partition, balance and create ghost elements all in the same step. */ diff --git a/tutorials/general/t8_step5_element_data_c_interface.c b/tutorials/general/t8_step5_element_data_c_interface.c index a32596f4ce..e1944ea76c 100644 --- a/tutorials/general/t8_step5_element_data_c_interface.c +++ b/tutorials/general/t8_step5_element_data_c_interface.c @@ -75,7 +75,7 @@ t8_step5_build_forest (sc_MPI_Comm comm, int level) 0.4 /* Coarsen if outside this radius. */ }; /* Start with a uniform forest. */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, 0, comm); t8_forest_t forest_apbg; /* Adapt, partition, balance and create ghost elements all in the same step. */ diff --git a/tutorials/general/t8_step6_stencil.cxx b/tutorials/general/t8_step6_stencil.cxx index d91924c052..ec0b4684fb 100644 --- a/tutorials/general/t8_step6_stencil.cxx +++ b/tutorials/general/t8_step6_stencil.cxx @@ -90,7 +90,7 @@ t8_step6_build_forest (sc_MPI_Comm comm, int dim, int level) 0.7 /* Coarsen if outside this radius. */ }; /* Start with a uniform forest. */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, comm); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, 0, comm); t8_forest_t forest_apbg; /* Adapt, partition, balance and create ghost elements all in one go. diff --git a/tutorials/general/t8_step7_interpolation.cxx b/tutorials/general/t8_step7_interpolation.cxx index 200fb243a3..8b5c255c27 100644 --- a/tutorials/general/t8_step7_interpolation.cxx +++ b/tutorials/general/t8_step7_interpolation.cxx @@ -293,7 +293,7 @@ t8_interpolation () t8_cmesh_t cmesh = t8_cmesh_new_from_class (T8_ECLASS_HEX, sc_MPI_COMM_WORLD); /* Construct a forest with one tree */ - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, 0, sc_MPI_COMM_WORLD); /* Build initial data array and set data for the local elements. */ data = T8_ALLOC (t8_step7_adapt_data, 1); diff --git a/tutorials/general/t8_tutorial_search.cxx b/tutorials/general/t8_tutorial_search.cxx index 7b42055df0..a7942bca79 100644 --- a/tutorials/general/t8_tutorial_search.cxx +++ b/tutorials/general/t8_tutorial_search.cxx @@ -407,7 +407,7 @@ main (int argc, char **argv) /* Build a cube cmesh with tet, hex, and prism trees. */ cmesh = t8_cmesh_new_hypercube_hybrid (comm, 0, 0); /* Build a uniform forest on it. */ - forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, comm); + forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), level, 0, 0, comm); /* Adapt the forest. We can reuse the forest variable, since the new adapted * forest will take ownership of the old forest and destroy it.