// ---------------------------------------------------------------------
//
// Copyright (C) 1998 - 2022 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE.md at
// the top level directory of deal.II.
//
// ---------------------------------------------------------------------


for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
  {
#if deal_II_dimension <= deal_II_space_dimension
    namespace DoFRenumbering
    \{
      namespace boost
      \{
        // TODO[WB]: also implement the following boost for hp-DoFHandlers etc.
      \}


      // non-boost functions:
      template void
      Cuthill_McKee<deal_II_dimension, deal_II_space_dimension>(
        DoFHandler<deal_II_dimension, deal_II_space_dimension> &,
        const bool,
        const bool,
        const std::vector<types::global_dof_index> &);

      template void
      compute_Cuthill_McKee<deal_II_dimension, deal_II_space_dimension>(
        std::vector<types::global_dof_index> &,
        const DoFHandler<deal_II_dimension, deal_II_space_dimension> &,
        const bool,
        const bool,
        const std::vector<types::global_dof_index> &,
        const unsigned int);

      template void
      component_wise<deal_II_dimension, deal_II_space_dimension>(
        DoFHandler<deal_II_dimension, deal_II_space_dimension> &,
        const std::vector<unsigned int> &);

      template void
      block_wise<deal_II_dimension, deal_II_space_dimension>(
        DoFHandler<deal_II_dimension, deal_II_space_dimension> &);

      template void
      subdomain_wise<deal_II_dimension, deal_II_space_dimension>(
        DoFHandler<deal_II_dimension, deal_II_space_dimension> &);

      template void
      compute_subdomain_wise(
        std::vector<types::global_dof_index> &new_dof_indices,
        const DoFHandler<deal_II_dimension, deal_II_space_dimension>
          &dof_handler);

      template void
      hierarchical(DoFHandler<deal_II_dimension, deal_II_space_dimension> &);

      template void
      support_point_wise(
        DoFHandler<deal_II_dimension, deal_II_space_dimension> &);

    \}
#endif
  }

// TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension,
// deal_II_space_dimension>
// where applicable and move to codimension cases above also when applicable
for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
  {
#if deal_II_dimension == deal_II_space_dimension
    namespace DoFRenumbering
    \{
      namespace boost
      \{
        // TODO[WB]: also implement the following boost for hp-DoFHandlers etc.
        template void
        Cuthill_McKee(DoFHandler<deal_II_dimension> &, bool, bool);

        template void
        compute_Cuthill_McKee(std::vector<dealii::types::global_dof_index> &,
                              const DoFHandler<deal_II_dimension> &,
                              bool,
                              bool);

        template void
        king_ordering(DoFHandler<deal_II_dimension> &, bool, bool);

        template void
        compute_king_ordering(std::vector<dealii::types::global_dof_index> &,
                              const DoFHandler<deal_II_dimension> &,
                              bool,
                              bool);

        template void
        minimum_degree(DoFHandler<deal_II_dimension> &, bool, bool);

        template void
        compute_minimum_degree(std::vector<dealii::types::global_dof_index> &,
                               const DoFHandler<deal_II_dimension> &,
                               bool,
                               bool);
      \}


      // non-boost functions:

      template void
      component_wise(DoFHandler<deal_II_dimension> &,
                     unsigned int,
                     const std::vector<unsigned int> &);

      template void
      block_wise<deal_II_dimension>(DoFHandler<deal_II_dimension> &,
                                    unsigned int);

      template void
      cell_wise<deal_II_dimension>(
        DoFHandler<deal_II_dimension> &,
        const std::vector<DoFHandler<deal_II_dimension>::active_cell_iterator>
          &);

      template void
      compute_cell_wise<deal_II_dimension>(
        std::vector<types::global_dof_index> &,
        std::vector<types::global_dof_index> &,
        const DoFHandler<deal_II_dimension> &,
        const std::vector<DoFHandler<deal_II_dimension>::active_cell_iterator>
          &);

      template void
      cell_wise<deal_II_dimension>(
        DoFHandler<deal_II_dimension> &,
        unsigned int,
        const std::vector<DoFHandler<deal_II_dimension>::level_cell_iterator>
          &);

      template void
      compute_cell_wise<deal_II_dimension>(
        std::vector<types::global_dof_index> &,
        std::vector<types::global_dof_index> &,
        const DoFHandler<deal_II_dimension> &,
        unsigned int,
        const std::vector<DoFHandler<deal_II_dimension>::level_cell_iterator>
          &);

      template void
      compute_downstream<deal_II_dimension>(
        std::vector<types::global_dof_index> &,
        std::vector<types::global_dof_index> &,
        const DoFHandler<deal_II_dimension> &,
        const Tensor<1, DoFHandler<deal_II_dimension>::space_dimension> &,
        const bool);

      template void
      clockwise_dg<deal_II_dimension>(DoFHandler<deal_II_dimension> &,
                                      const Point<deal_II_dimension> &,
                                      bool);

      template void
      compute_clockwise_dg<deal_II_dimension>(
        std::vector<types::global_dof_index> &,
        const DoFHandler<deal_II_dimension> &,
        const Point<deal_II_dimension> &,
        const bool);

      // Renumbering for DoFHandler


      template void
      downstream(
        DoFHandler<deal_II_dimension> &,
        const Tensor<1, DoFHandler<deal_II_dimension>::space_dimension> &,
        const bool);

      // MG

      template void
      downstream(
        DoFHandler<deal_II_dimension> &,
        const unsigned int,
        const Tensor<1, DoFHandler<deal_II_dimension>::space_dimension> &,
        const bool);

      template void
      clockwise_dg(DoFHandler<deal_II_dimension> &,
                   const unsigned int,
                   const Point<deal_II_dimension> &,
                   bool);

      // Generic numbering schemes

      template void
      random<deal_II_dimension>(DoFHandler<deal_II_dimension> &);

      template void
      compute_random<deal_II_dimension>(std::vector<types::global_dof_index> &,
                                        const DoFHandler<deal_II_dimension> &);

      template void
      random<deal_II_dimension>(DoFHandler<deal_II_dimension> &,
                                const unsigned int);

      template void
      compute_random<deal_II_dimension>(std::vector<types::global_dof_index> &,
                                        const DoFHandler<deal_II_dimension> &,
                                        const unsigned int);

      template void
      sort_selected_dofs_back<deal_II_dimension>(
        DoFHandler<deal_II_dimension> &,
        const std::vector<bool> &);

      template void
      compute_sort_selected_dofs_back<deal_II_dimension>(
        std::vector<types::global_dof_index> &,
        const DoFHandler<deal_II_dimension> &,
        const std::vector<bool> &);

      template void
      Cuthill_McKee<deal_II_dimension>(
        DoFHandler<deal_II_dimension> &,
        const unsigned int,
        const bool,
        const std::vector<types::global_dof_index> &);
    \}
#endif
  }


for (deal_II_dimension : DIMENSIONS;
     deal_II_scalar_vectorized : REAL_SCALARS_VECTORIZED)
  {
    namespace DoFRenumbering
    \{
      template void
      matrix_free_data_locality<deal_II_dimension,
                                deal_II_dimension,
                                deal_II_scalar_vectorized::value_type,
                                deal_II_scalar_vectorized>(
        DoFHandler<deal_II_dimension, deal_II_dimension> &,
        const MatrixFree<deal_II_dimension,
                         deal_II_scalar_vectorized::value_type,
                         deal_II_scalar_vectorized> &);

      template std::vector<types::global_dof_index>
      compute_matrix_free_data_locality<deal_II_dimension,
                                        deal_II_dimension,
                                        deal_II_scalar_vectorized::value_type,
                                        deal_II_scalar_vectorized>(
        const DoFHandler<deal_II_dimension, deal_II_dimension> &,
        const MatrixFree<deal_II_dimension,
                         deal_II_scalar_vectorized::value_type,
                         deal_II_scalar_vectorized> &);

      template void
      matrix_free_data_locality<
        deal_II_dimension,
        deal_II_dimension,
        deal_II_scalar_vectorized::value_type,
        MatrixFree<deal_II_dimension,
                   deal_II_scalar_vectorized::value_type,
                   deal_II_scalar_vectorized>::AdditionalData>(
        DoFHandler<deal_II_dimension, deal_II_dimension> &,
        const AffineConstraints<deal_II_scalar_vectorized::value_type> &,
        const MatrixFree<deal_II_dimension,
                         deal_II_scalar_vectorized::value_type,
                         deal_II_scalar_vectorized>::AdditionalData &);

      template std::vector<types::global_dof_index>
      compute_matrix_free_data_locality<
        deal_II_dimension,
        deal_II_dimension,
        deal_II_scalar_vectorized::value_type,
        MatrixFree<deal_II_dimension,
                   deal_II_scalar_vectorized::value_type,
                   deal_II_scalar_vectorized>::AdditionalData>(
        const DoFHandler<deal_II_dimension, deal_II_dimension> &,
        const AffineConstraints<deal_II_scalar_vectorized::value_type> &,
        const MatrixFree<deal_II_dimension,
                         deal_II_scalar_vectorized::value_type,
                         deal_II_scalar_vectorized>::AdditionalData &);
    \}
  }

for (deal_II_dimension : DIMENSIONS;
     deal_II_float_vectorized : FLOAT_VECTORIZED)
  {
    namespace DoFRenumbering
    \{
      template void
      matrix_free_data_locality<
        deal_II_dimension,
        deal_II_dimension,
        double,
        MatrixFree<deal_II_dimension,
                   deal_II_float_vectorized::value_type,
                   deal_II_float_vectorized>::AdditionalData>(
        DoFHandler<deal_II_dimension, deal_II_dimension> &,
        const AffineConstraints<double> &,
        const MatrixFree<deal_II_dimension,
                         deal_II_float_vectorized::value_type,
                         deal_II_float_vectorized>::AdditionalData &);

      template std::vector<types::global_dof_index>
      compute_matrix_free_data_locality<
        deal_II_dimension,
        deal_II_dimension,
        double,
        MatrixFree<deal_II_dimension,
                   deal_II_float_vectorized::value_type,
                   deal_II_float_vectorized>::AdditionalData>(
        const DoFHandler<deal_II_dimension, deal_II_dimension> &,
        const AffineConstraints<double> &,
        const MatrixFree<deal_II_dimension,
                         deal_II_float_vectorized::value_type,
                         deal_II_float_vectorized>::AdditionalData &);
    \}
  }
