Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion mesh_handle/mesh.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "element.hxx"
#include "competence_pack.hxx"
#include "internal/adapt.hxx"
#include "t8_forest/t8_forest_balance.h"
#include "t8_forest/t8_forest_types.h"
#include <t8_forest/t8_forest_general.h>
#include <t8_forest/t8_forest_ghost.h>
#include <vector>
Expand Down Expand Up @@ -166,6 +168,17 @@ class mesh {
return m_forest;
}

/** Check if the local elements of the mesh are balanced.
* The mesh is said to be balanced if the level difference between face neighbors is at most 1.
* at most +1 or -1 of the element's level.
* \return true if the local elements are balanced, false otherwise.
*/
bool
is_balanced ()
{
return t8_forest_is_balanced (m_forest);
}

// --- Methods to access elements. ---
/**
* Returns a constant iterator to the first (local) mesh element.
Expand Down Expand Up @@ -280,6 +293,48 @@ class mesh {
t8_forest_set_adapt (m_uncommitted_forest.value (), m_forest, detail::mesh_adapt_callback_wrapper, false);
}

/** If this function is called, the mesh will be partitioned on committing.
* The partitioning is done according to the SFC and each rank is assigned
* the same (maybe +1) number of elements.
* \note The partition is carried out only when \ref commit is called.
* \note This setting can be combined with \ref set_adapt and \ref set_balance. The order in which
* these operations are executed is always 1) Adapt 2) Partition 3) Balance.
* \param [in] set_for_coarsening If true, the partitions are choose such that coarsening
* an element once is a process local operation. Default is false.
*/
void
set_partition (bool set_for_coarsening = false)
{
if (!m_uncommitted_forest.has_value ()) {
t8_forest_t new_forest;
t8_forest_init (&new_forest);
m_uncommitted_forest = new_forest;
}
t8_forest_set_partition (m_uncommitted_forest.value (), m_forest, set_for_coarsening);
}

/** If this function is called, the mesh will be balanced on committing.
* The mesh is said to be balanced if the element level between face neighbors differs by at most 1.
* \note The balance is carried out only when \ref commit is called.
* \param [in] no_repartition Balance constructs several intermediate steps that
* are refined from each other. In order to maintain a balanced load, a repartitioning is performed in each
* round and the resulting mesh is load-balanced per default.
* Set \a no_repartition to true if this behaviour is not desired.
* If \a no_repartition is false (default), an additional call of \ref set_partition is not necessary.
* \note This setting can be combined with \ref set_adapt and \ref set_partition. The order in which
* these operations are executed is always 1) Adapt 2) Partition 3) Balance.
*/
void
set_balance (bool no_repartition = false)
{
if (!m_uncommitted_forest.has_value ()) {
t8_forest_t new_forest;
t8_forest_init (&new_forest);
m_uncommitted_forest = new_forest;
}
t8_forest_set_balance (m_uncommitted_forest.value (), m_forest, no_repartition);
}

/** Enable or disable the creation of a layer of ghost elements.
* \param [in] do_ghost If true a ghost layer will be created.
* \param [in] ghost_type Controls which neighbors count as ghost elements,
Expand Down Expand Up @@ -317,7 +372,7 @@ class mesh {
t8_forest_ref (m_forest);
t8_forest_commit (m_uncommitted_forest.value ());
// Check if we adapted and unregister the adapt context if so.
if (detail::adapt_registry::get (m_uncommitted_forest.value ()) != nullptr) {
if (detail::adapt_registry::get (m_forest) != nullptr) {
detail::adapt_registry::unregister_context (m_forest);
if (!std::is_void<TElementDataType>::value) {
t8_global_infof (
Expand Down
16 changes: 8 additions & 8 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,11 @@ endif()
add_t8_cpp_test( NAME t8_gtest_vector_split_serial SOURCES t8_helper_functions/t8_gtest_vector_split.cxx )

if( T8CODE_BUILD_MESH_HANDLE )
add_t8_cpp_test( NAME t8_gtest_mesh_handle_parallel SOURCES mesh_handle/t8_gtest_mesh_handle.cxx )
add_t8_cpp_test( NAME t8_gtest_compare_handle_to_forest_serial SOURCES mesh_handle/t8_gtest_compare_handle_to_forest.cxx )
add_t8_cpp_test( NAME t8_gtest_handle_ghost_parallel SOURCES mesh_handle/t8_gtest_ghost.cxx )
add_t8_cpp_test( NAME t8_gtest_custom_competence_serial SOURCES mesh_handle/t8_gtest_custom_competence.cxx )
add_t8_cpp_test( NAME t8_gtest_cache_competence_serial SOURCES mesh_handle/t8_gtest_cache_competence.cxx )
add_t8_cpp_test( NAME t8_gtest_handle_data_parallel SOURCES mesh_handle/t8_gtest_handle_data.cxx )
add_t8_cpp_test( NAME t8_gtest_handle_adapt_serial SOURCES mesh_handle/t8_gtest_adapt.cxx )
endif()
add_t8_cpp_test( NAME t8_gtest_mesh_handle_parallel SOURCES mesh_handle/t8_gtest_mesh_handle.cxx )
add_t8_cpp_test( NAME t8_gtest_compare_handle_to_forest_serial SOURCES mesh_handle/t8_gtest_compare_handle_to_forest.cxx )
add_t8_cpp_test( NAME t8_gtest_handle_ghost_parallel SOURCES mesh_handle/t8_gtest_ghost.cxx )
add_t8_cpp_test( NAME t8_gtest_custom_competence_serial SOURCES mesh_handle/t8_gtest_custom_competence.cxx )
add_t8_cpp_test( NAME t8_gtest_cache_competence_serial SOURCES mesh_handle/t8_gtest_cache_competence.cxx )
add_t8_cpp_test( NAME t8_gtest_handle_data_parallel SOURCES mesh_handle/t8_gtest_handle_data.cxx )
add_t8_cpp_test( NAME t8_gtest_adapt_partition_balance_parallel SOURCES mesh_handle/t8_gtest_adapt_partition_balance.cxx )
endif()
1 change: 1 addition & 0 deletions test/mesh_handle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ Therefore, the tests are structured as follows:
- [t8_gtest_cache_competence.cxx](t8_gtest_cache_competence.cxx) tests that *all predefined caching competences* work as intended.
- [t8_gtest_ghost.cxx](t8_gtest_ghost.cxx) checks ghosts and the neighbor algorithm. Furthermore tests if *all functions work also for ghost cells* if applicable.
- [t8_gtest_handle_data.cxx](t8_gtest_handle_data.cxx) tests that user and element data functionality works as intended.
- [t8_gtest_adapt_partition_balance.cxx](t8_gtest_adapt_partition_balance.cxx) implements tests for the adapt, partition and balance routines of mesh handle.
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@ along with t8code; if not, write to the Free Software Foundation, Inc.,
*/

/**
* \file t8_gtest_adapt.cxx
* Tests for the adapt routines of mesh handles.
* This tests uses the callback and user data of tutorial step 3 as example.
* The adaptation criterion is to look at the midpoint coordinates of the current element and if
* they are inside a sphere around a given midpoint we refine, if they are outside, we coarsen.
* \file t8_gtest_adapt_partition_balance.cxx
* Tests for the adapt, partition and balance routines of mesh handle.
*/
#include "t8_types/t8_vec.h"
#include <gtest/gtest.h>
Expand All @@ -49,6 +46,8 @@ struct dummy_user_data
};

/** Callback function for the mesh handle to decide for refining or coarsening of (a family of) elements.
* The adaptation criterion is to look at the midpoint coordinates of the current element and if
* they are inside a sphere around a given midpoint we refine, if they are outside, we coarsen.
* The function header fits the definition of \ref TMesh::adapt_callback_type_with_userdata.
* \tparam TMeshClass The mesh handle class.
* \param [in] mesh The mesh that should be adapted.
Expand Down Expand Up @@ -137,10 +136,11 @@ forest_adapt_callback_refine_second ([[maybe_unused]] t8_forest_t forest, [[mayb
return 0;
}

/** Test the adapt routine of a mesh handle.
* We compare the result to a classically adapted forest with similar callback.
/** Test the adapt, partition and balance routines of a mesh handle.
* The test compares the results of the mesh handle to a forest adapted with the same criterion and balanced and partitioned similarly.
* Therefore, the check is based on the assumption that the forest functionality works as intended and is tested elsewhere.
*/
TEST (t8_gtest_handle_adapt, compare_adapt_with_forest)
TEST (t8_gtest_handle_adapt, compare_with_forest)
{
// Define forest, a mesh handle and user data.
const int level = 3;
Expand All @@ -163,23 +163,41 @@ TEST (t8_gtest_handle_adapt, compare_adapt_with_forest)
mesh_class::mesh_adapt_callback_wrapper<dummy_user_data> (adapt_callback_test<mesh_class>, user_data));
mesh_handle.commit ();
// Adapt forest classically.
forest = t8_forest_new_adapt (forest, forest_adapt_callback_example, 0, 1, &user_data);
forest = t8_forest_new_adapt (forest, forest_adapt_callback_example, 0, 0, &user_data);

// Compare results.
EXPECT_TRUE (t8_forest_is_equal (mesh_handle.get_forest (), forest));

// Adapt the mesh handle again and apply partition and balance.
mesh_handle.set_balance ();
mesh_handle.set_partition ();
mesh_handle.set_adapt (
mesh_class::mesh_adapt_callback_wrapper<dummy_user_data> (adapt_callback_test<mesh_class>, user_data));
mesh_handle.commit ();
EXPECT_TRUE (mesh_handle.is_balanced ());

// Compare the results again to an appropriate forest.
t8_forest_t forest_compare;
t8_forest_init (&forest_compare);
t8_forest_set_user_data (forest_compare, &user_data);
t8_forest_set_adapt (forest_compare, forest, forest_adapt_callback_example, false);
t8_forest_set_partition (forest_compare, NULL, false);
t8_forest_set_balance (forest_compare, NULL, false);
t8_forest_commit (forest_compare);
EXPECT_TRUE (t8_forest_is_equal (mesh_handle.get_forest (), forest_compare));

// Adapt again with the second callback.
mesh_handle.set_adapt (mesh_adapt_callback_test_refine_second<mesh_class>);
mesh_handle.commit ();

t8_forest_t forest_refine_second;
t8_forest_init (&forest_refine_second);
t8_forest_set_adapt (forest_refine_second, forest, forest_adapt_callback_refine_second, false);
t8_forest_commit (forest_refine_second);
t8_forest_t forest_refine;
t8_forest_init (&forest_refine);
t8_forest_set_adapt (forest_refine, forest_compare, forest_adapt_callback_refine_second, false);
t8_forest_commit (forest_refine);

// Compare results.
EXPECT_TRUE (t8_forest_is_equal (mesh_handle.get_forest (), forest_refine_second));
EXPECT_TRUE (t8_forest_is_equal (mesh_handle.get_forest (), forest_refine));

// Clean up.
t8_forest_unref (&forest_refine_second);
t8_forest_unref (&forest_refine);
}
Loading