.. _program_listing_file_mesh_handle_internal_adapt.hxx: Program Listing for File adapt.hxx ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``mesh_handle/internal/adapt.hxx``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* 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 #include #include #include #include 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 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 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 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>& get_map () { static std::unordered_map> 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