/****************************************************************************
**  SIONLIB     http://www.fz-juelich.de/jsc/sionlib                       **
*****************************************************************************
**  Copyright (c) 2008-2019                                                **
**  Forschungszentrum Juelich, Juelich Supercomputing Centre               **
**                                                                         **
**  See the file COPYRIGHT in the package base directory for details       **
****************************************************************************/

/*!
 * \cond sion_internal
 * \file
 */

#ifndef SION_SION_MPI_INTERNAL_GEN_H
#define SION_SION_MPI_INTERNAL_GEN_H

#ifdef SION_MPI

#include <mpi.h>
#include <stdint.h>
#include <stdio.h>

#include "sion_flags.h"
#include "sion_generic.h"
#include "sion_generic_internal.h"

#define USE_PMPIno
#ifdef USE_PMPI
#define MPI_Comm_rank PMPI_Comm_rank
#define MPI_Comm_size PMPI_Comm_size
#define MPI_Gather PMPI_Gather
#define MPI_Scatter PMPI_Scatter
#define MPI_Bcast PMPI_Bcast
#define MPI_Barrier PMPI_Barrier
#define MPI_Comm_split PMPI_Comm_split
#define MPI_Send PMPI_Send
#define MPI_Recv PMPI_Recv
#endif

struct _sion_filedesc_mpiadd_struct {
  MPI_Comm gComm;
  MPI_Comm lComm;
  double ts;
  int blocksize;
  int step;
};
typedef struct _sion_filedesc_mpiadd_struct _sion_filedesc_mpiadd;

/*!\brief Splits a Communicator in numfiles different communicators
 *
 * @param[in]    numFiles     number of files
 * @param[in]    gComm        global communicator
 * @param[out]   filenumber   file number
 * @param[out]   lrank        local rank
 * @param[out]   lsize        local size
 *
 */
int _sion_gen_info_from_gcomm_mpi(int numFiles, MPI_Comm gComm, int *filenumber, int *lrank, int *lsize);
int _sion_get_info_from_splitted_comm_mpi(MPI_Comm gComm, MPI_Comm lComm, int *numComm, int *CommNumber, int *lrank, int *lsize);

int _sion_errorprint_mpi(int rc, int level, const char *format, ...);

int _sion_paropen_mapped_mpi(char *fname, const _sion_flags_store *flags_store, int *numFiles, MPI_Comm gComm, int *nlocaltasks,
  int **globalranks, int64_t **chunksizes, int **mapping_filenrs, int **mapping_lranks, int32_t *fsblksize, FILE **fileptr);

typedef enum { _SION_MPI_MULTIFILE_NUMBER, _SION_MPI_MULTIFILE_COMMUNICATOR } _sion_mpi_multifile_mode;

typedef union {
  int number;
  MPI_Comm communicator;
} _sion_mpi_multifile_data;

struct sion_mpi_options {
  sion_generic_options generic_options;

  _sion_mpi_multifile_mode multifile_mode; // default: _SION_MPI_MULTIFILE_NUMBER
  _sion_mpi_multifile_data multifile; // default: 1
};

#define SION_MPI_OPTIONS_INIT \
  (sion_mpi_options) \
  { \
    .generic_options = SION_GENERIC_OPTIONS_INIT, .multifile_mode = _SION_MPI_MULTIFILE_NUMBER, .multifile.number = 1, \
  }

#endif

#endif

/// \endcond
