Program Listing for File adapt.hxx
↰ Return to documentation for file (mesh_handle/internal/adapt.hxx)
/*
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 classes in parallel.
Copyright (C) 2026 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.
*/
#pragma once
#include <t8.h>
#include <t8_forest/t8_forest_general.h>
#include <mesh_handle/mesh.hxx>
#include <memory>
#include <span>
namespace t8_mesh_handle
{
namespace detail
{
struct mesh_adapt_context_base
{
virtual ~mesh_adapt_context_base () = default;
virtual int
adapt_mesh (const t8_locidx_t lelement_handle_id, const int num_elements)
= 0;
};
template <typename TMeshClass>
struct mesh_adapt_context final: mesh_adapt_context_base
{
mesh_adapt_context (TMeshClass& mesh_handle, typename TMeshClass::adapt_callback_type adapt_callback)
: m_mesh_handle (mesh_handle), m_adapt_callback (std::move (adapt_callback))
{
}
int
adapt_mesh (const t8_locidx_t lelement_handle_id, const int num_elements) override
{
// Check if adapt callback is set and call it using the correct mesh handle function arguments.
T8_ASSERTF (m_adapt_callback, "No adapt callback set.");
std::span<const typename TMeshClass::element_class> element_view (&m_mesh_handle[lelement_handle_id], num_elements);
return m_adapt_callback (m_mesh_handle, element_view);
}
private:
TMeshClass& m_mesh_handle;
typename TMeshClass::adapt_callback_type m_adapt_callback;
};
class adapt_registry {
public:
static void
register_context (t8_forest_t forest, std::unique_ptr<mesh_adapt_context_base> context)
{
auto& map = get_map ();
auto [it, inserted] = map.emplace (forest, std::move (context));
if (!inserted) {
t8_global_errorf ("ERROR: Context already registered!");
}
}
static void
unregister_context (t8_forest_t forest)
{
auto& map = get_map ();
[[maybe_unused]] const auto erased = map.erase (forest);
T8_ASSERT (erased == 1);
}
static mesh_adapt_context_base*
get (t8_forest_t forest)
{
const auto& map = get_map ();
const auto it = map.find (forest);
return it != map.end () ? it->second.get () : nullptr;
}
private:
static std::unordered_map<t8_forest_t, std::unique_ptr<mesh_adapt_context_base>>&
get_map ()
{
static std::unordered_map<t8_forest_t, std::unique_ptr<mesh_adapt_context_base>> map;
return map;
}
};
int
mesh_adapt_callback_wrapper ([[maybe_unused]] t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree,
t8_eclass_t tree_class, t8_locidx_t lelement_id, [[maybe_unused]] const t8_scheme* scheme,
const int is_family, const int num_elements, t8_element_t* elements[])
{
if (is_family && !scheme->elements_are_family (tree_class, elements)) {
t8_global_errorf ("ERROR: The mesh handle does not support deleted elements.");
return 0; // No adaptation as default.
}
// Get static adapt context from the registry.
// Via this, we can access the mesh handle and the user defined adapt callback that uses mesh handle functionality.
auto* context = adapt_registry::get (forest_from);
if (!context) {
t8_global_errorf (
"ERROR: Something went wrong while registering the adaptation callbacks. Please check your implementation.");
return 0; // No adaptation as default.
}
// Convert to index used in the mesh handle.
const t8_locidx_t mesh_index = t8_forest_get_tree_element_offset (forest_from, which_tree) + lelement_id;
// Call the actual adapt callback stored in the context.
return context->adapt_mesh (mesh_index, num_elements);
}
} // namespace detail
} // namespace t8_mesh_handle