/*
 * Copyright (C)  NHR@FAU, University Erlangen-Nuremberg.
 * All rights reserved. This file is part of nusif-solver.
 * Use of this source code is governed by a MIT style
 * license that can be found in the LICENSE file.
 */
#ifndef __COMM_H_
#define __COMM_H_
#if defined(_MPI)
#include <mpi.h>
#endif

enum direction { LEFT = 0, RIGHT, BOTTOM, TOP, NDIRS };
enum dimension { IDIM = 0, JDIM, NDIMS };
enum cdimension { CJDIM = 0, CIDIM };
enum layer { HALO = 0, BULK };
enum op { MAX = 0, SUM };

typedef struct {
    int rank;
    int size;
#if defined(_MPI)
    MPI_Comm comm;
    MPI_Datatype bufferTypes[NDIRS];
    MPI_Aint sdispls[NDIRS];
    MPI_Aint rdispls[NDIRS];
#endif
    int neighbours[NDIRS];
    int coords[NDIMS], dims[NDIMS];
    int imaxLocal, jmaxLocal;
} Comm;

extern int sizeOfRank(int rank, int size, int N);
extern void commInit(Comm* c, int argc, char** argv);
extern void commTestInit(Comm* c, double* p, double* f, double* g);
extern void commTestWrite(Comm* c, double* p, double* f, double* g);
extern void commFinalize(Comm* c);
extern void commPartition(Comm* c, int jmax, int imax);
extern void commPrintConfig(Comm*);
extern void commExchange(Comm*, double*);
extern void commShift(Comm* c, double* f, double* g);
extern void commReduction(double* v, int op);
extern int commIsBoundary(Comm* c, int direction);
extern void commUpdateDatatypes(Comm*, Comm*, int, int);
extern void commFreeCommunicator(Comm*);
extern void commCollectResult(Comm* c,
    double* ug,
    double* vg,
    double* pg,
    double* u,
    double* v,
    double* p,
    int jmax,
    int imax);

static inline int commIsMaster(Comm* c) { return c->rank == 0; }
#endif // __COMM_H_
