// @HEADER
// *****************************************************************************
//        MueLu: A package for multigrid based preconditioning
//
// Copyright 2012 NTESS and the MueLu contributors.
// SPDX-License-Identifier: BSD-3-Clause
// *****************************************************************************
// @HEADER

#ifndef MUELU_NODEPARTITIONINTERFACE_DECL_HPP
#define MUELU_NODEPARTITIONINTERFACE_DECL_HPP

#include "MueLu_ConfigDefs.hpp"

#if defined(HAVE_MPI)

#include <Xpetra_Matrix_fwd.hpp>
#include <Xpetra_VectorFactory_fwd.hpp>

#include "MueLu_SingleLevelFactoryBase.hpp"
#include "MueLu_NodePartitionInterface_fwd.hpp"

#include "MueLu_Level_fwd.hpp"
#include "MueLu_FactoryBase_fwd.hpp"

namespace MueLu {

/*!
  @class NodePartitionInterface
  @brief Partitioning within a node only
  @ingroup Rebalancing

  This interface provides partitioning within a node

  ## Input/output of NodePartitionInterface ##

  ### User parameters of NodePartitionInterface ###
  Parameter | type | default | master.xml | validated | requested | description
  ----------|------|---------|:----------:|:---------:|:---------:|------------
  | A                                      | Factory | null  |   | * | * | Generating factory of the matrix A used during the prolongator smoothing process |
  | Coordinates                            | Factory | null  |   | * | (*) | Factory generating coordinates vector used for rebalancing. The coordinates are only needed when the chosen algorithm is 'multijagged' or 'rcb'.
  | ParameterList                          | ParamterList | null |  | * |  | NodePartition parameters
  | number of partitions                   | GO      | - |  |  |  | Short-cut parameter set by RepartitionFactory. Avoid repartitioning algorithms if only one partition is necessary (see details below)
  | NodeComm                               | Factory | null  |   | * | (*) | Factory generating NodeComm.

  The * in the @c master.xml column denotes that the parameter is defined in the @c master.xml file.<br>
  The * in the @c validated column means that the parameter is declared in the list of valid input parameters (see NodePartitionInterface::GetValidParameters).<br>
  The * in the @c requested column states that the data is requested as input with all dependencies (see NodePartitionInterface::DeclareInput).

  ### Variables provided by NodePartitionInterface ###

  After NodePartitionInterface::Build the following data is available (if requested)

  Parameter | generated by | description
  ----------|--------------|------------
  | Partition       | NodePartitionInterface   | GOVector based on the Row map of A (DOF-based) containing the process id the DOF should be living in after rebalancing/repartitioning

  The "Partition" vector is used as input for the RepartitionFactory class.
  If Re-partitioning/rebalancing is necessary it uses the "Partition" variable to create the corresponding Xpetra::Import object which then is used
  by the RebalanceFactory classes (e.g., RebalanceAcFactory, RebalanceTransferFactory,...) to rebalance the coarse level operators.

  The RepartitionHeuristicFactory calculates how many partitions are to be built when performing rebalancing.
  It stores the result in the "number of partitions" variable on the current level (type = GO).
  If it is "number of partitions=1" we skip the NodePartition call and just create an dummy "Partition" vector containing zeros only.
  If no repartitioning is necessary (i.e., just keep the current partitioning) we return "Partition = Teuchos::null".
  If "number of partitions" > 1, the algorithm tries to find the requested number of partitions.

*/

// FIXME: this class should not be templated
template <class Scalar,
          class LocalOrdinal  = DefaultLocalOrdinal,
          class GlobalOrdinal = DefaultGlobalOrdinal,
          class Node          = DefaultNode>
class NodePartitionInterface : public SingleLevelFactoryBase {
#undef MUELU_NODEPARTITIONINTERFACE_SHORT
#include "MueLu_UseShortNames.hpp"

 public:
  //! @name Constructors/Destructors
  //@{

  //! Constructor
  NodePartitionInterface();

  //! Destructor
  virtual ~NodePartitionInterface() {}
  //@}

  RCP<const ParameterList> GetValidParameterList() const;

  //! @name Input
  //@{
  void DeclareInput(Level& currentLevel) const;
  //@}

  //! @name Build methods.
  //@{
  void Build(Level& currentLevel) const;

  //@}

 private:
  RCP<ParameterList> defaultNodePartitionParams;

};  // class NodePartitionInterface

}  // namespace MueLu

#define MUELU_NODEPARTITIONINTERFACE_SHORT
#endif  // if defined(HAVE_MPI)

#endif  // MUELU_NODEPARTITIONINTERFACE_DECL_HPP
