Program Listing for File EMFexchange.cpp
↰ Return to documentation for file (hydro/electromotiveforce/EMFexchange.cpp
)
// ***********************************************************************************
// Idefix MHD astrophysical code
// Copyright(C) 2020-2022 Geoffroy R. J. Lesur <geoffroy.lesur@univ-grenoble-alpes.fr>
// and other code contributors
// Licensed under CeCILL 2.1 License, see COPYING for more information
// ***********************************************************************************
#include "electroMotiveForce.hpp"
#include "hydro.hpp"
#include "dataBlock.hpp"
#ifdef WITH_MPI
void ElectroMotiveForce::ExchangeAll() {
if(data->mygrid->nproc[IDIR]>1) this->ExchangeX1();
if(data->mygrid->nproc[JDIR]>1) this->ExchangeX2();
if(data->mygrid->nproc[KDIR]>1) this->ExchangeX3();
}
// Exchange EMFs in X1
void ElectroMotiveForce::ExchangeX1() {
idfx::pushRegion("Emf::ExchangeX1");
// Load the buffers with data
int ileft,iright,jbeg,jend,kbeg,kend;
int ny;
[[maybe_unused]] int nz;
IdefixArray1D<real> BufferLeft=BufferSendX1[faceLeft];
IdefixArray1D<real> BufferRight=BufferSendX1[faceRight];
IdefixArray3D<real> ey=this->ey;
IdefixArray3D<real> ez=this->ez;
// If MPI Persistent, start receiving even before the buffers are filled
MPI_Status sendStatus[2];
MPI_Status recvStatus[2];
double tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Startall(2, recvRequestX1));
idfx::mpiCallsTimer += MPI_Wtime() - tStart;
BoundaryType lbound = data->lbound[IDIR];
BoundaryType rbound = data->rbound[IDIR];
// Coordinates of the ghost region which needs to be transfered
ileft = data->beg[IDIR];
iright = data->end[IDIR];
jbeg = data->beg[JDIR];
jend = data->end[JDIR];
ny = jend - jbeg;
kbeg = data->beg[KDIR];
kend = data->end[KDIR];
nz = kend - kbeg;
idefix_for("LoadBufferX1Emfz",kbeg,kend,jbeg,jend+1,
KOKKOS_LAMBDA (int k, int j) {
BufferLeft( (j-jbeg) + (k-kbeg)*(ny+1) ) = ez(k,j,ileft);
BufferRight( (j-jbeg) + (k-kbeg)*(ny+1) ) = ez(k,j,iright);
}
);
#if DIMENSIONS == 3
int Vsindex = (ny+1)*nz;
idefix_for("LoadBufferX1Emfy",kbeg,kend+1,jbeg,jend,
KOKKOS_LAMBDA (int k, int j) {
BufferLeft( (j-jbeg) + (k-kbeg)*ny + Vsindex ) = ey(k,j,ileft);
BufferRight( (j-jbeg) + (k-kbeg)*ny + Vsindex ) = ey(k,j,iright);
}
);
#endif
// Wait for completion before sending out everything
Kokkos::fence();
tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Startall(2, sendRequestX1));
// Wait for buffers to be received
MPI_Waitall(2,recvRequestX1,recvStatus);
MPI_Waitall(2, sendRequestX1, sendStatus);
idfx::mpiCallsTimer += MPI_Wtime() - tStart;
// Unpack
BufferLeft=BufferRecvX1[faceLeft];
BufferRight=BufferRecvX1[faceRight];
// We average the edge emfs zones
idefix_for("StoreBufferX1Emfz",kbeg,kend,jbeg,jend+1,
KOKKOS_LAMBDA (int k, int j) {
if(lbound == internal || lbound == periodic) {
ez(k,j,ileft) = HALF_F*(
BufferLeft( (j-jbeg) + (k-kbeg)*(ny+1) ) + ez(k,j,ileft) );
}
if(rbound == internal || rbound == periodic) {
ez(k,j,iright) = HALF_F*(
BufferRight( (j-jbeg) + (k-kbeg)*(ny+1) ) + ez(k,j,iright) );
}
});
#if DIMENSIONS == 3
Vsindex = (ny+1)*nz;
idefix_for("StoreBufferX1Emfy",kbeg,kend+1,jbeg,jend,
KOKKOS_LAMBDA (int k, int j) {
if(lbound == internal || lbound == periodic) {
ey(k,j,ileft) = HALF_F*(
BufferLeft( (j-jbeg) + (k-kbeg)*ny +Vsindex) + ey(k,j,ileft) );
}
if(rbound == internal || rbound == periodic) {
ey(k,j,iright) = HALF_F*(
BufferRight( (j-jbeg) + (k-kbeg)*ny +Vsindex) + ey(k,j,iright) );
}
});
#endif
idfx::popRegion();
}
// Exchange EMFs in X2
void ElectroMotiveForce::ExchangeX2() {
idfx::pushRegion("Emf::ExchangeX2");
// Load the buffers with data
int jleft,jright,ibeg,iend,kbeg,kend;
int nx;
[[maybe_unused]] int nz;
IdefixArray1D<real> BufferLeft=BufferSendX2[faceLeft];
IdefixArray1D<real> BufferRight=BufferSendX2[faceRight];
IdefixArray3D<real> ex=this->ex;
IdefixArray3D<real> ez=this->ez;
// If MPI Persistent, start receiving even before the buffers are filled
double tStart = MPI_Wtime();
MPI_Status sendStatus[2];
MPI_Status recvStatus[2];
MPI_SAFE_CALL(MPI_Startall(2, recvRequestX2));
idfx::mpiCallsTimer += MPI_Wtime() - tStart;
BoundaryType lbound = data->lbound[JDIR];
BoundaryType rbound = data->rbound[JDIR];
// Coordinates of the ghost region which needs to be transfered
ibeg = data->beg[IDIR];
iend = data->end[IDIR];
nx = iend - ibeg;
jleft = data->beg[JDIR];
jright = data->end[JDIR];
kbeg = data->beg[KDIR];
kend = data->end[KDIR];
nz = kend - kbeg;
idefix_for("LoadBufferX2Emfz",kbeg,kend,ibeg,iend+1,
KOKKOS_LAMBDA (int k, int i) {
BufferLeft( (i-ibeg) + (k-kbeg)*(nx+1) ) = ez(k,jleft,i);
BufferRight( (i-ibeg) + (k-kbeg)*(nx+1) ) = ez(k,jright,i);
}
);
#if DIMENSIONS == 3
int Vsindex = (nx+1)*nz;
idefix_for("LoadBufferX1Emfx",kbeg,kend+1,ibeg,iend,
KOKKOS_LAMBDA (int k, int i) {
BufferLeft( (i-ibeg) + (k-kbeg)*nx + Vsindex ) = ex(k,jleft,i);
BufferRight( (i-ibeg) + (k-kbeg)*nx + Vsindex ) = ex(k,jright,i);
}
);
#endif
// Wait for completion before sending out everything
Kokkos::fence();
tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Startall(2, sendRequestX2));
// Wait for buffers to be received
MPI_Waitall(2,recvRequestX2,recvStatus);
MPI_Waitall(2, sendRequestX2, sendStatus);
idfx::mpiCallsTimer += MPI_Wtime() - tStart;
// Unpack
BufferLeft=BufferRecvX2[faceLeft];
BufferRight=BufferRecvX2[faceRight];
// We average the edge emfs zones
idefix_for("StoreBufferX2Emfz",kbeg,kend,ibeg,iend+1,
KOKKOS_LAMBDA (int k, int i) {
if(lbound == internal || lbound == periodic) {
ez(k,jleft,i) = HALF_F*(
BufferLeft( (i-ibeg) + (k-kbeg)*(nx+1) ) + ez(k,jleft,i) );
}
if(rbound == internal || rbound == periodic) {
ez(k,jright,i) = HALF_F*(
BufferRight( (i-ibeg) + (k-kbeg)*(nx+1) ) + ez(k,jright,i) );
}
});
#if DIMENSIONS == 3
Vsindex = (nx+1)*nz;
idefix_for("StoreBufferX1Emfy",kbeg,kend+1,ibeg,iend,
KOKKOS_LAMBDA (int k, int i) {
if(lbound == internal || lbound == periodic) {
ex(k,jleft,i) = HALF_F*(
BufferLeft( (i-ibeg) + (k-kbeg)*nx +Vsindex) + ex(k,jleft,i) );
}
if(rbound == internal || rbound == periodic) {
ex(k,jright,i) = HALF_F*(
BufferRight( (i-ibeg) + (k-kbeg)*nx +Vsindex) + ex(k,jright,i) );
}
});
#endif
idfx::popRegion();
}
// Exchange EMFs in X3
void ElectroMotiveForce::ExchangeX3() {
idfx::pushRegion("Emf::ExchangeX3");
// Load the buffers with data
int kleft,kright,ibeg,iend,jbeg,jend;
int nx,ny;
IdefixArray1D<real> BufferLeft=BufferSendX3[faceLeft];
IdefixArray1D<real> BufferRight=BufferSendX3[faceRight];
IdefixArray3D<real> ex=this->ex;
IdefixArray3D<real> ey=this->ey;
int Vsindex = 0;
// If MPI Persistent, start receiving even before the buffers are filled
double tStart = MPI_Wtime();
MPI_Status sendStatus[2];
MPI_Status recvStatus[2];
MPI_SAFE_CALL(MPI_Startall(2, recvRequestX3));
idfx::mpiCallsTimer += MPI_Wtime() - tStart;
BoundaryType lbound = data->lbound[KDIR];
BoundaryType rbound = data->rbound[KDIR];
// Coordinates of the ghost region which needs to be transfered
ibeg = data->beg[IDIR];
iend = data->end[IDIR];
nx = iend - ibeg;
jbeg = data->beg[JDIR];
jend = data->end[JDIR];
ny = jend - jbeg;
kleft = data->beg[KDIR];
kright = data->end[KDIR];
idefix_for("LoadBufferX3Emfx",jbeg,jend+1,ibeg,iend,
KOKKOS_LAMBDA (int j, int i) {
BufferLeft( (i-ibeg) + (j-jbeg)*nx ) = ex(kleft,j,i);
BufferRight( (i-ibeg) + (j-jbeg)*nx ) = ex(kright,j,i);
}
);
Vsindex = nx*(ny+1);
idefix_for("LoadBufferX3Emfy",jbeg,jend,ibeg,iend+1,
KOKKOS_LAMBDA (int j, int i) {
BufferLeft( (i-ibeg) + (j-jbeg)*(nx+1) + Vsindex ) = ey(kleft,j,i);
BufferRight( (i-ibeg) + (j-jbeg)*(nx+1) + Vsindex ) = ey(kright,j,i);
}
);
// Wait for completion before sending out everything
Kokkos::fence();
tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Startall(2, sendRequestX3));
// Wait for buffers to be received
MPI_Waitall(2,recvRequestX3,recvStatus);
MPI_Waitall(2, sendRequestX3, sendStatus);
idfx::mpiCallsTimer += MPI_Wtime() - tStart;
// Unpack
BufferLeft=BufferRecvX3[faceLeft];
BufferRight=BufferRecvX3[faceRight];
// We average the edge emfs zones
idefix_for("StoreBufferX3Emfx",jbeg,jend+1,ibeg,iend,
KOKKOS_LAMBDA (int j, int i) {
if(lbound == internal || lbound == periodic) {
ex(kleft,j,i) = HALF_F*(
BufferLeft( (i-ibeg) + (j-jbeg)*nx ) + ex(kleft,j,i) );
}
if(rbound == internal || rbound == periodic) {
ex(kright,j,i) = HALF_F*(
BufferRight( (i-ibeg) + (j-jbeg)*nx ) + ex(kright,j,i) );
}
});
Vsindex = nx*(ny+1);
idefix_for("StoreBufferX3Emfy",jbeg,jend,ibeg,iend+1,
KOKKOS_LAMBDA (int j, int i) {
if(lbound == internal || lbound == periodic) {
ey(kleft,j,i) = HALF_F*(
BufferLeft( (i-ibeg) + (j-jbeg)*(nx+1) + Vsindex ) + ey(kleft,j,i) );
}
if(rbound == internal || rbound == periodic) {
ey(kright,j,i) = HALF_F*(
BufferRight( (i-ibeg) + (j-jbeg)*(nx+1) + Vsindex ) + ey(kright,j,i) );
}
});
idfx::popRegion();
}
#endif