00001 #include "laxfriedrichsmpioverlap.h"
00002 #include "netmpi.h"
00003 #include "fxyslabid.h"
00004 #include "numericmethods.h"
00005
00006 #define SEND_GHOSTCELL 201
00007 #define DEAD_ZONE_VALUE 202
00008 void LaxFriedrichsMPIOverlap::setCommunicationBuffers(OrthoMesh &mesh,int mesh_overlap)
00009 {
00010
00011 unsigned elemsInXY = mesh.numElemY()*mesh.numElemZ();
00012 double dx = mesh.get_dx();
00013 double tol = dx/4.0;
00014
00015
00016 fDeadZone.resize(mesh.numFaces(),ACTIVE_ZONE);
00017 if (NetMPI::rank() != 0)
00018 {
00019 double X0 = mesh.getP()[0];
00020 double X1 = X0 + mesh_overlap*dx;
00021 double X2 = X0 + 2*mesh_overlap*dx;
00022
00023 cLDeadZoneRcvMap.reserve(mesh_overlap*elemsInXY);
00024 cLDeadZoneSndMap.reserve(mesh_overlap*elemsInXY);
00025 FXYSlabId fRcv(X0,X1,tol);
00026 FXYSlabId fSnd(X1,X2,tol);
00027 mesh.getCellsInFunctionDomain(fRcv,cLDeadZoneRcvMap);
00028 mesh.getCellsInFunctionDomain(fSnd,cLDeadZoneSndMap);
00029 cLDeadZoneRcv.reinit(cLDeadZoneRcvMap.size());
00030 cLDeadZoneSnd.reinit(cLDeadZoneSndMap.size());
00031
00032 LGhostCellRcvMap.reserve(elemsInXY);
00033 LGhostCellSndMap.reserve(elemsInXY);
00034 FXYSlabId f2Rcv(X1-dx,X1,tol);
00035 FXYSlabId f2Snd(X1,X1+dx,tol);
00036 mesh.getCellsInFunctionDomain(f2Rcv,LGhostCellRcvMap);
00037 mesh.getCellsInFunctionDomain(f2Snd,LGhostCellSndMap);
00038 LGhostCellRcv.reinit(LGhostCellRcvMap.size());
00039 LGhostCellSnd.reinit(LGhostCellSndMap.size());
00040 assert(LGhostCellRcvMap.size() == elemsInXY);
00041 assert(LGhostCellSndMap.size() == elemsInXY);
00042
00043 FXYSlabId fLFaces(X0,X1-dx,tol);
00044 mesh.tagFacesInDomain(fLFaces,fDeadZone, LEFT_DEAD_ZONE);
00045
00046
00047 }
00048 if (!NetMPI::isLastProcess())
00049 {
00050 double X2 = mesh.getQ()[0];
00051 double X1 = X2 - mesh_overlap*dx;
00052 double X0 = X2 - 2*mesh_overlap*dx;
00053
00054 cRDeadZoneRcvMap.reserve(mesh_overlap*elemsInXY);
00055 cRDeadZoneSndMap.reserve(mesh_overlap*elemsInXY);
00056 FXYSlabId fRcv(X1,X2,tol);
00057 FXYSlabId fSnd(X0,X1,tol);
00058 mesh.getCellsInFunctionDomain(fRcv,cRDeadZoneRcvMap);
00059 mesh.getCellsInFunctionDomain(fSnd,cRDeadZoneSndMap);
00060 cRDeadZoneRcv.reinit(cRDeadZoneRcvMap.size());
00061 cRDeadZoneSnd.reinit(cRDeadZoneSndMap.size());
00062
00063 RGhostCellRcvMap.reserve(elemsInXY);
00064 RGhostCellSndMap.reserve(elemsInXY);
00065 FXYSlabId f2Rcv(X1,X1+dx,tol);
00066 FXYSlabId f2Snd(X1-dx,X1,tol);
00067 mesh.getCellsInFunctionDomain(f2Rcv,RGhostCellRcvMap);
00068 mesh.getCellsInFunctionDomain(f2Snd,RGhostCellSndMap);
00069 RGhostCellRcv.reinit(RGhostCellRcvMap.size());
00070 RGhostCellSnd.reinit(RGhostCellSndMap.size());
00071 assert(RGhostCellRcvMap.size() == elemsInXY);
00072 assert(RGhostCellSndMap.size() == elemsInXY);
00073
00074 FXYSlabId fRFaces(X1+dx,X2,tol);
00075 mesh.tagFacesInDomain(fRFaces,fDeadZone,RIGHT_DEAD_ZONE);
00076
00077
00078
00079 }
00080
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 LaxFriedrichsMPIOverlap::~LaxFriedrichsMPIOverlap()
00092 {
00093
00094 }
00095
00096 LaxFriedrichsMPIOverlap::LaxFriedrichsMPIOverlap(OrthoMesh &mesh,Function3D &fInitU,const VecDouble &cPor,Function3D &fPrescribedU,FaceFluxFunction &flux, double CFL,int mesh_overlap)
00097 :LaxFriedrichsMethod(mesh,fInitU,cPor,fPrescribedU,flux,CFL)
00098 {
00099 NetMPI::trace("Entering Communication Buffers ");
00100 setCommunicationBuffers(mesh,mesh_overlap);
00101 NetMPI::trace("End");
00102
00103 }
00104
00105
00106 void LaxFriedrichsMPIOverlap::iterate(double t, double tEnd)
00107 {
00108 unsigned posCell,negCell;
00109 VecReq _req(4);
00110 double timeInterval = tEnd-t;
00111 double localDt = this->calculateTimeStep(m_mesh,timeInterval,m_CFL,getPorosity(),m_flux);
00112 double dt=negotiateTimeStep(localDt);
00113 NetMPI::trace("Lax Negotiating dt: Sent %g, got %g",localDt,dt);
00114
00115
00116 int nIteraction = (int) round(timeInterval/dt);
00117
00118
00119 for (int count = 0; count < nIteraction; count++)
00120 {
00121
00122 OrthoMesh::Face_It face = m_mesh.begin_face();
00123 unsigned nFaces = m_mesh.numFaces();
00124
00125 m_cValuesPrev=m_cValues;
00126
00127
00128 VecTag::iterator itDZ = fDeadZone.begin();
00129 for (unsigned faceIndex=0;faceIndex < nFaces; faceIndex++,face++,itDZ++)
00130 {
00131
00132 if (*itDZ != ACTIVE_ZONE)
00133 continue;
00134
00135
00136 double SwPos,SwNeg;
00137 this->getValuesOfTheFaceCells(m_mesh,m_fValues,m_cValuesPrev,face,SwNeg,SwPos);
00138
00139
00140
00141
00142 face->getValidCellIndices(posCell,negCell);
00143
00144
00145 double posPor = getPorosity()(posCell);
00146 double negPor = getPorosity()(negCell);
00147
00148
00149 double mPor = (posPor + negPor)/2.0;
00150
00151
00152 double flux;
00153 double bc = (getBC(faceIndex));
00154 if (bc == INFINITY)
00155 {
00156
00157
00158
00159
00160
00161
00162 flux = dt*face->areaPerCellVol() * m_flux.fluxAtFace(face,faceIndex,posCell,negCell,SwPos,SwNeg) - mPor*(SwNeg-SwPos)/6.0;
00163 }
00164 else
00165 {
00166 flux = dt*face->areaPerCellVol() * m_flux.fluxAtFace(face,faceIndex,posCell,negCell,bc,bc);
00167 }
00168
00169
00170
00171
00172 if (face->hasPosCell())
00173 m_cValues(face->getPosCell()) += - flux/posPor;
00174
00175 if (face->hasNegCell())
00176 m_cValues(face->getNegCell()) += + flux/negPor;
00177 }
00178 updateGhostCells();
00179
00180 }
00181 updateDeadZone();
00182 }
00183
00184
00185
00186
00187
00188
00189
00190 void LaxFriedrichsMPIOverlap::updateGhostCells()
00191 {
00192 NetMPI::exchangeDataRedBlack(LGhostCellSndMap,LGhostCellSnd,LGhostCellRcvMap,LGhostCellRcv,
00193 RGhostCellSndMap,RGhostCellSnd,RGhostCellRcvMap,RGhostCellRcv,
00194 m_cValues,SEND_GHOSTCELL);
00195
00196 }
00197
00198 void LaxFriedrichsMPIOverlap::updateDeadZone()
00199 {
00200 NetMPI::exchangeDataRedBlack(cLDeadZoneSndMap,cLDeadZoneSnd,cLDeadZoneRcvMap,cLDeadZoneRcv,
00201 cRDeadZoneSndMap,cRDeadZoneSnd,cRDeadZoneRcvMap,cRDeadZoneRcv,
00202 m_cValues,DEAD_ZONE_VALUE);
00203
00204 }
00205
00206
00207 void LaxFriedrichsMPIOverlap::unitTest()
00208 {
00209 std::ostream &out = NetMPI::getLog();
00210 out << "\n\nLeft Ghost Rcv\n";
00211 m_mesh.printCells(LGhostCellRcvMap,out);
00212 out << "\n\nLeft Ghost Snd\n";
00213 m_mesh.printCells(LGhostCellSndMap,out);
00214 out << "\n\nRight Ghost Rcv\n";
00215 m_mesh.printCells(RGhostCellRcvMap,out);
00216 out << "\n\nRight Ghost Snd\n";
00217 m_mesh.printCells(RGhostCellSndMap,out);
00218
00219 }
00220
00221
00222 double LaxFriedrichsMPIOverlap::negotiateTimeStep(double dt)
00223 {
00224 double dd;
00225 MPI_Allreduce(&dt,&dd,1,MPI_DOUBLE,MPI_MIN,MPI_COMM_WORLD);
00226 return dd;
00227 }