Program Listing for File t8_scheme.hxx

Return to documentation for file (src/t8_schemes/t8_scheme.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) 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.
*/

#ifndef T8_SCHEME_HXX
#define T8_SCHEME_HXX

#include <variant>
#include <vector>
#include <t8_refcount.h>
#include <t8_eclass.h>
#include <t8_schemes/t8_default/t8_default.hxx>
#include <t8_schemes/t8_default/t8_default_vertex/t8_default_vertex.hxx>
#include <t8_schemes/t8_default/t8_default_line/t8_default_line.hxx>
#include <t8_schemes/t8_default/t8_default_quad/t8_default_quad.hxx>
#include <t8_schemes/t8_default/t8_default_hex/t8_default_hex.hxx>
#include <t8_schemes/t8_default/t8_default_tri/t8_default_tri.hxx>
#include <t8_schemes/t8_default/t8_default_tet/t8_default_tet.hxx>
#include <t8_schemes/t8_default/t8_default_prism/t8_default_prism.hxx>
#include <t8_schemes/t8_default/t8_default_pyramid/t8_default_pyramid.hxx>
#include <t8_schemes/t8_standalone/t8_standalone.hxx>
#include <t8_schemes/t8_standalone/t8_standalone_implementation.hxx>
#include <string>
#if T8_ENABLE_DEBUG
// Only needed for t8_debug_print_type
#include <typeinfo>

template <typename TType>
inline std::string &
t8_debug_print_type ()
{
  static std::string type_name = typeid (TType).name ();
  return type_name;
}
#endif  // T8_ENABLE_DEBUG

class t8_scheme {
  friend class t8_scheme_builder;

 public:
  t8_scheme ()
  {
    t8_refcount_init (&rc);
  };

  ~t8_scheme ()
  {
    if (sc_refcount_is_active (&rc)) {
      T8_ASSERT (t8_refcount_is_last (&rc));
      t8_refcount_unref (&rc);
    }
    t8_debugf ("Deleted the scheme.\n");
  };

  /* clang-format off */

  using scheme_var = std::variant<
                                /* Default schemes */
                                t8_default_scheme_vertex,
                                t8_default_scheme_line,
                                t8_default_scheme_quad,
                                t8_default_scheme_tri,
                                t8_default_scheme_hex,
                                t8_default_scheme_tet,
                                t8_default_scheme_prism,
                                t8_default_scheme_pyramid,
                                t8_standalone_scheme<T8_ECLASS_VERTEX>,
                                t8_standalone_scheme<T8_ECLASS_LINE>,
                                t8_standalone_scheme<T8_ECLASS_QUAD>,
                                t8_standalone_scheme<T8_ECLASS_HEX>
                                >;
  /* clang-format on */

  using scheme_container = std::vector<scheme_var>;
 private:
  scheme_container eclass_schemes;
  mutable t8_refcount_t
    rc;
 public:
  inline void
  ref () const
  {
    t8_refcount_ref (&rc);
  }

  inline int
  unref () const
  {
    const int remaining = rc.refcount - 1;
    if (t8_refcount_unref (&rc)) {
      t8_debugf ("Deleting the scheme.\n");
      delete this;
    }
    return remaining;
  }

  inline size_t
  get_num_eclass_schemes () const
  {
    return eclass_schemes.size ();
  }

  template <class TEclassScheme>
  inline bool
  check_eclass_scheme_type (const t8_eclass_t tree_class) const
  {
    return std::holds_alternative<TEclassScheme> (eclass_schemes[tree_class]);
  }

  inline t8_eclass_t
  get_eclass_scheme_eclass (const t8_eclass_t tree_class) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.get_eclass (); }, eclass_schemes[tree_class]);
  }

  inline size_t
  get_eclass_scheme_dimension (const t8_eclass_t tree_class) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.get_dimension (); }, eclass_schemes[tree_class]);
  }

  inline size_t
  get_element_size (const t8_eclass_t tree_class) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.get_element_size (); }, eclass_schemes[tree_class]);
  };

  inline bool
  refines_irregular (const t8_eclass_t tree_class) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.refines_irregular (); }, eclass_schemes[tree_class]);
  };

  inline int
  get_maxlevel (const t8_eclass_t tree_class) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.get_maxlevel (); }, eclass_schemes[tree_class]);
  };

  inline int
  element_get_level (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_level (element); }, eclass_schemes[tree_class]);
  };

  inline void
  element_copy (const t8_eclass_t tree_class, const t8_element_t *source, t8_element_t *dest) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_copy (source, dest); }, eclass_schemes[tree_class]);
  };

  inline int
  element_compare (const t8_eclass_t tree_class, const t8_element_t *elem1, const t8_element_t *elem2) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_compare (elem1, elem2); },
                       eclass_schemes[tree_class]);
  };

  inline bool
  element_is_equal (const t8_eclass_t tree_class, const t8_element_t *elem1, const t8_element_t *elem2) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_is_equal (elem1, elem2); },
                       eclass_schemes[tree_class]);
  };

  inline bool
  element_is_refinable (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_is_refinable (element); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_parent (const t8_eclass_t tree_class, const t8_element_t *element, t8_element_t *parent) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_parent (element, parent); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_num_siblings (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_num_siblings (element); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_sibling (const t8_eclass_t tree_class, const t8_element_t *element, const int sibid,
                       t8_element_t *sibling) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_sibling (element, sibid, sibling); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_num_corners (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_num_corners (element); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_num_faces (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_num_faces (element); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_max_num_faces (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_max_num_faces (element); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_num_children (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_num_children (element); },
                       eclass_schemes[tree_class]);
  };

  inline int
  get_max_num_children (const t8_eclass_t tree_class) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.get_max_num_children (); }, eclass_schemes[tree_class]);
  };

  inline int
  element_get_num_face_children (const t8_eclass_t tree_class, const t8_element_t *element, const int face) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_num_face_children (element, face); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_face_corner (const t8_eclass_t tree_class, const t8_element_t *element, const int face,
                           const int corner) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_face_corner (element, face, corner); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_corner_face (const t8_eclass_t tree_class, const t8_element_t *element, const int corner,
                           const int face) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_corner_face (element, corner, face); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_child (const t8_eclass_t tree_class, const t8_element_t *element, const int childid,
                     t8_element_t *child) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_child (element, childid, child); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_children (const t8_eclass_t tree_class, const t8_element_t *element, const int length,
                        t8_element_t *c[]) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_children (element, length, c); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_child_id (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_child_id (element); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_ancestor_id (const t8_eclass_t tree_class, const t8_element_t *element, const int level) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_ancestor_id (element, level); },
                       eclass_schemes[tree_class]);
  };

  inline bool
  elements_are_family (const t8_eclass_t tree_class, t8_element_t *const *fam) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.elements_are_family (fam); }, eclass_schemes[tree_class]);
  };

  inline void
  element_get_nca (const t8_eclass_t tree_class, const t8_element_t *elem1, const t8_element_t *elem2,
                   t8_element_t *const nca) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_nca (elem1, elem2, nca); },
                       eclass_schemes[tree_class]);
  };

  inline t8_element_shape_t
  element_get_face_shape (const t8_eclass_t tree_class, const t8_element_t *element, const int face) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_face_shape (element, face); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_children_at_face (const t8_eclass_t tree_class, const t8_element_t *element, const int face,
                                t8_element_t *children[], int num_children, int *child_indices) const
  {
    return std::visit (
      [&] (auto &&scheme) {
        return scheme.element_get_children_at_face (element, face, children, num_children, child_indices);
      },
      eclass_schemes[tree_class]);
  };

  inline int
  element_face_get_child_face (const t8_eclass_t tree_class, const t8_element_t *element, const int face,
                               const int face_child) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_face_get_child_face (element, face, face_child); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_face_get_parent_face (const t8_eclass_t tree_class, const t8_element_t *element, const int face) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_face_get_parent_face (element, face); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_tree_face (const t8_eclass_t tree_class, const t8_element_t *element, const int face) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_tree_face (element, face); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_transform_face (const t8_eclass_t tree_class, const t8_element_t *elem1, t8_element_t *elem2,
                          const int orientation, const int sign, const int is_smaller_face) const
  {
    return std::visit (
      [&] (auto &&scheme) { return scheme.element_transform_face (elem1, elem2, orientation, sign, is_smaller_face); },
      eclass_schemes[tree_class]);
  };

  inline int
  element_extrude_face (const t8_eclass_t tree_class, const t8_element_t *face, t8_element_t *element,
                        const int root_face) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_extrude_face (face, element, root_face, this); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_boundary_face (const t8_eclass_t tree_class, const t8_element_t *element, const int face,
                             t8_element_t *boundary) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_boundary_face (element, face, boundary, this); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_first_descendant_face (const t8_eclass_t tree_class, const t8_element_t *element, const int face,
                                     t8_element_t *first_desc, const int level) const
  {
    return std::visit (
      [&] (auto &&scheme) { return scheme.element_get_first_descendant_face (element, face, first_desc, level); },
      eclass_schemes[tree_class]);
  };

  inline void
  element_get_last_descendant_face (const t8_eclass_t tree_class, const t8_element_t *element, const int face,
                                    t8_element_t *last_desc, const int level) const
  {
    return std::visit (
      [&] (auto &&scheme) { return scheme.element_get_last_descendant_face (element, face, last_desc, level); },
      eclass_schemes[tree_class]);
  };

  inline bool
  element_is_root_boundary (const t8_eclass_t tree_class, const t8_element_t *element, const int face) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_is_root_boundary (element, face); },
                       eclass_schemes[tree_class]);
  };

  inline int
  element_get_face_neighbor_inside (const t8_eclass_t tree_class, const t8_element_t *element, t8_element_t *neigh,
                                    const int face, int *neigh_face) const
  {
    return std::visit (
      [&] (auto &&scheme) { return scheme.element_get_face_neighbor_inside (element, neigh, face, neigh_face); },
      eclass_schemes[tree_class]);
  };

  inline t8_element_shape_t
  element_get_shape (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_shape (element); }, eclass_schemes[tree_class]);
  };

  inline void
  element_set_linear_id (const t8_eclass_t tree_class, t8_element_t *element, const int level,
                         const t8_linearidx_t id) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_set_linear_id (element, level, id); },
                       eclass_schemes[tree_class]);
  };

  inline t8_linearidx_t
  element_get_linear_id (const t8_eclass_t tree_class, const t8_element_t *element, const int level) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_linear_id (element, level); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_first_descendant (const t8_eclass_t tree_class, const t8_element_t *element, t8_element_t *desc,
                                const int level) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_first_descendant (element, desc, level); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_last_descendant (const t8_eclass_t tree_class, const t8_element_t *element, t8_element_t *desc,
                               const int level) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_get_last_descendant (element, desc, level); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_construct_successor (const t8_eclass_t tree_class, const t8_element_t *element, t8_element_t *successor) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_construct_successor (element, successor); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_get_vertex_reference_coords (const t8_eclass_t tree_class, const t8_element_t *element, const int vertex,
                                       double coords[]) const
  {
    return std::visit (
      [&] (auto &&scheme) { return scheme.element_get_vertex_reference_coords (element, vertex, coords); },
      eclass_schemes[tree_class]);
  };

  inline void
  element_get_reference_coords (const t8_eclass_t tree_class, const t8_element_t *element, const double *ref_coords,
                                const size_t num_coords, double *out_coords) const
  {
    return std::visit (
      [&] (auto &&scheme) { return scheme.element_get_reference_coords (element, ref_coords, num_coords, out_coords); },
      eclass_schemes[tree_class]);
  };

  inline t8_gloidx_t
  element_count_leaves (const t8_eclass_t tree_class, const t8_element_t *t, const int level) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_count_leaves (t, level); },
                       eclass_schemes[tree_class]);
  };

  inline t8_gloidx_t
  count_leaves_from_root (const t8_eclass_t tree_class, const int level) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.count_leaves_from_root (level); },
                       eclass_schemes[tree_class]);
  };

#if T8_ENABLE_DEBUG
  inline int
  element_is_valid (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_is_valid (element); }, eclass_schemes[tree_class]);
  };

  inline void
  element_debug_print (const t8_eclass_t tree_class, const t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_debug_print (element); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_to_string (const t8_eclass_t tree_class, const t8_element_t *element, char *debug_string,
                     const int string_size) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_to_string (element, debug_string, string_size); },
                       eclass_schemes[tree_class]);
  };
#endif

  inline void
  element_new (const t8_eclass_t tree_class, const int length, t8_element_t **elements) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_new (length, elements); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_init (const t8_eclass_t tree_class, const int length, t8_element_t *elements) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_init (length, elements); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_deinit (const t8_eclass_t tree_class, const int length, t8_element_t *elements) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_deinit (length, elements); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_destroy (const t8_eclass_t tree_class, const int length, t8_element_t **elements) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_destroy (length, elements); },
                       eclass_schemes[tree_class]);
  };

  inline void
  set_to_root (const t8_eclass_t tree_class, t8_element_t *element) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.set_to_root (element); }, eclass_schemes[tree_class]);
  };

  inline void
  element_MPI_Pack (const t8_eclass_t tree_class, t8_element_t **const elements, const unsigned int count,
                    void *send_buffer, int buffer_size, int *position, sc_MPI_Comm comm) const
  {
    return std::visit (
      [&] (auto &&scheme) {
        return scheme.element_MPI_Pack (elements, count, send_buffer, buffer_size, position, comm);
      },
      eclass_schemes[tree_class]);
  };

  inline void
  element_MPI_Pack_size (const t8_eclass_t tree_class, const unsigned int count, sc_MPI_Comm comm, int *pack_size) const
  {
    return std::visit ([&] (auto &&scheme) { return scheme.element_MPI_Pack_size (count, comm, pack_size); },
                       eclass_schemes[tree_class]);
  };

  inline void
  element_MPI_Unpack (t8_eclass_t tree_class, void *recvbuf, const int buffer_size, int *position,
                      t8_element_t **elements, const unsigned int count, sc_MPI_Comm comm) const
  {
    return std::visit (
      [&] (auto &&scheme) { return scheme.element_MPI_Unpack (recvbuf, buffer_size, position, elements, count, comm); },
      eclass_schemes[tree_class]);
  };
};

#endif /* !T8_SCHEME_HXX */