#include <laxfriedrichsmethodmpi.h>
This class implements the Lax Fridrichs method in parallel. Each process has a subdomain. The subdomains may have intersection (mesh overllaping) because of the Dynamic module alghorithm, but the conservative method consider the region that extend into the other subdomain as a "Dead Zone". No computations are made in Dead Zone. In the sketch above, DZ1 is the deadzone of the domain Omega 1 and DZ2 is the dead zone of the process in domain Omega 2. When all the processes finish to iterate the solution, each process receives the correct values of its dead zones from the neighbors.Note that generally we need just the values of the boundaries of the dead zone to iterate the transport. The cells that belong to the dead zone and are at the boundary of the active zone are called here Ghost Cells. The other values of the dead zone are needed only when the process need to pass the value of the saturations to the dynamic module and the processes commute these values only when it is time to run the dynamic module.
--------|----|----| |Dz2 | DZ1| --------|--- |----| Omega 1 |-----------------| Omega 2 |-------------------|
The domain decomposition is the most simple possible. The subdomains are made of cuts planes that are orthoghonal with respect to the X direction.
Definition at line 25 of file laxfriedrichsmethodmpi.h.
enum LaxFriedrichsMethodMPI::FACES_ZONE [protected] |
Definition at line 50 of file laxfriedrichsmethodmpi.h.
00050 {ACTIVE_ZONE=0,LEFT_DEAD_ZONE=1,RIGHT_DEAD_ZONE=2};
LaxFriedrichsMethodMPI::LaxFriedrichsMethodMPI | ( | OrthoMesh & | mesh, | |
Function3D & | fInitU, | |||
const VecDouble & | cPor, | |||
Function3D & | fPrescribedU, | |||
FaceFluxFunction & | flux, | |||
double | CFL, | |||
int | mesh_overlap | |||
) |
Definition at line 158 of file laxfriedrichsmethodmpi.cpp.
00159 :LaxFriedrichsMethod(mesh,fInitU,cPor,fPrescribedU,flux,CFL),mesh_overlap(mesh_overlap) 00160 { 00161 NetMPI::trace("Entering Communication Buffers "); 00162 setCommunicationBuffers(mesh,mesh_overlap); 00163 NetMPI::trace("End"); 00164 00165 }
LaxFriedrichsMethodMPI::~LaxFriedrichsMethodMPI | ( | ) | [virtual] |
Definition at line 153 of file laxfriedrichsmethodmpi.cpp.
void LaxFriedrichsMethodMPI::iterate | ( | double | t, | |
double | tEnd | |||
) | [virtual] |
Reimplemented in RussanovMethodMPI.
Definition at line 168 of file laxfriedrichsmethodmpi.cpp.
00169 { 00170 unsigned posCell,negCell; 00171 VecReq _req(4); 00172 double timeInterval = tEnd-t; 00173 double localDt = this->calculateTimeStep(m_mesh,timeInterval,m_CFL,getPorosity(),m_flux); 00174 double dt=negotiateTimeStep(localDt); 00175 NetMPI::trace("Lax Negotiating dt: Sent %g, got %g",localDt,dt); 00176 00177 //Get the number of iterations 00178 int nIteraction = (int) round(timeInterval/dt); //number of iteractions 00179 00180 //For each time step 00181 for (int count = 0; count < nIteraction; count++) 00182 { 00183 //Get the face iterator and the number of faces. 00184 OrthoMesh::Face_It face = m_mesh.begin_face(); 00185 unsigned nFaces = m_mesh.numFaces(); 00186 00187 m_cValuesPrev=m_cValues; 00188 00189 //For each face 00190 VecTag::iterator itDZ = fDeadZone.begin(); 00191 for (unsigned faceIndex=0;faceIndex < nFaces; faceIndex++,face++,itDZ++) 00192 { 00193 //Check if the face is in active zone 00194 if (*itDZ != ACTIVE_ZONE) 00195 continue; 00196 00197 //Get the values of the previous solution in the right and left of the face 00198 double SwPos,SwNeg; 00199 this->getValuesOfTheFaceCells(m_mesh,m_fValues,m_cValuesPrev,face,SwNeg,SwPos); 00200 00201 //Get the values of the cells that contain the face. 00202 //If the face is at boundary, it has just one cell. 00203 //In this case the method getAdjCells() return posCell == negCell 00204 face->getValidCellIndices(posCell,negCell); 00205 00206 //Get the porsity 00207 double posPor = getPorosity()(posCell); 00208 double negPor = getPorosity()(negCell); 00209 00210 // 00211 double mPor = (posPor + negPor)/2.0; 00212 00213 //See if the face has prescribed boundary condition BC 00214 double flux; 00215 double bc = (getBC(faceIndex)); 00216 if (bc == INFINITY) 00217 { 00218 /* 00219 The face doesnt have boundary condition BC 00220 proceed to the usual computation of the flux 00221 to calculate the amount of the mass passed through 00222 the face and divide it by the cell volume 00223 */ 00224 flux = dt*face->areaPerCellVol() * m_flux.fluxAtFace(face,faceIndex,posCell,negCell,SwPos,SwNeg) - mPor*(SwNeg-SwPos)/6.0; 00225 } 00226 else //the face has BC, so dont add the stability term 00227 { 00228 flux = dt*face->areaPerCellVol() * m_flux.fluxAtFace(face,faceIndex,posCell,negCell,bc,bc); 00229 } 00230 00231 00232 00233 //printf("face %d = %g,Pos: %d,Neg %d, SwPos = %g,SwNeg = %g \n",faceIndex,flux,face->getPosCellIndex(),face->getNegCellIndex(),SwPos,SwNeg); 00234 if (face->hasPosCell()) 00235 m_cValues(face->getPosCell()) += - flux/posPor; 00236 00237 if (face->hasNegCell()) 00238 m_cValues(face->getNegCell()) += + flux/negPor; 00239 } 00240 updateGhostCells(); 00241 00242 } 00243 updateDeadZone(); 00244 }
double LaxFriedrichsMethodMPI::negotiateTimeStep | ( | double | dt | ) |
Negotiate which time step each node will use
Definition at line 293 of file laxfriedrichsmethodmpi.cpp.
void LaxFriedrichsMethodMPI::setCommunicationBuffers | ( | OrthoMesh & | mesh, | |
int | mesh_overlap | |||
) | [protected] |
Initialize everything related to communication among the processes.
mesh | ||
mesh_overlap | The size of the mesh overlap (how many elements a dead zone have) |
Definition at line 65 of file laxfriedrichsmethodmpi.cpp.
00066 { 00067 if (mesh_overlap == 0) 00068 return setCommunicationBuffersWithNoOverlap(mesh); 00069 00070 //Set communication buffers 00071 unsigned elemsInXY = mesh.numElemY()*mesh.numElemZ(); 00072 double dx = mesh.get_dx(); 00073 double tol = dx/4.0; 00074 00075 00076 fDeadZone.resize(mesh.numFaces(),ACTIVE_ZONE); 00077 00078 if (NetMPI::rank() != 0) 00079 { 00080 double X0 = mesh.getP()[0]; 00081 double X1 = X0 + mesh_overlap*dx; 00082 double X2 = X0 + 2*mesh_overlap*dx; 00083 00084 cLDeadZoneRcvMap.reserve(mesh_overlap*elemsInXY); 00085 cLDeadZoneSndMap.reserve(mesh_overlap*elemsInXY); 00086 FXYSlabId fRcv(X0,X1,tol); 00087 FXYSlabId fSnd(X1,X2,tol); 00088 mesh.getCellsIndicesInDomain(fRcv,cLDeadZoneRcvMap); 00089 mesh.getCellsIndicesInDomain(fSnd,cLDeadZoneSndMap); 00090 cLDeadZoneRcv.reinit(cLDeadZoneRcvMap.size()); 00091 cLDeadZoneSnd.reinit(cLDeadZoneSndMap.size()); 00092 00093 LGhostCellRcvMap.reserve(elemsInXY); 00094 LGhostCellSndMap.reserve(elemsInXY); 00095 FXYSlabId f2Rcv(X1-dx,X1,tol); 00096 FXYSlabId f2Snd(X1,X1+dx,tol); 00097 mesh.getCellsIndicesInDomain(f2Rcv,LGhostCellRcvMap); 00098 mesh.getCellsIndicesInDomain(f2Snd,LGhostCellSndMap); 00099 LGhostCellRcv.reinit(LGhostCellRcvMap.size()); 00100 LGhostCellSnd.reinit(LGhostCellSndMap.size()); 00101 assert(LGhostCellRcvMap.size() == elemsInXY); 00102 assert(LGhostCellSndMap.size() == elemsInXY); 00103 00104 FXYSlabId fLFaces(X0,X1-dx,tol); 00105 mesh.tagFacesInDomain(fLFaces,fDeadZone, LEFT_DEAD_ZONE); 00106 00107 00108 } 00109 if (!NetMPI::isLastProcess()) 00110 { 00111 double X2 = mesh.getQ()[0]; 00112 double X1 = X2 - mesh_overlap*dx; 00113 double X0 = X2 - 2*mesh_overlap*dx; 00114 00115 cRDeadZoneRcvMap.reserve(mesh_overlap*elemsInXY); 00116 cRDeadZoneSndMap.reserve(mesh_overlap*elemsInXY); 00117 FXYSlabId fRcv(X1,X2,tol); 00118 FXYSlabId fSnd(X0,X1,tol); 00119 mesh.getCellsIndicesInDomain(fRcv,cRDeadZoneRcvMap); 00120 mesh.getCellsIndicesInDomain(fSnd,cRDeadZoneSndMap); 00121 cRDeadZoneRcv.reinit(cRDeadZoneRcvMap.size()); 00122 cRDeadZoneSnd.reinit(cRDeadZoneSndMap.size()); 00123 00124 RGhostCellRcvMap.reserve(elemsInXY); 00125 RGhostCellSndMap.reserve(elemsInXY); 00126 FXYSlabId f2Rcv(X1,X1+dx,tol); 00127 FXYSlabId f2Snd(X1-dx,X1,tol); 00128 mesh.getCellsIndicesInDomain(f2Rcv,RGhostCellRcvMap); 00129 mesh.getCellsIndicesInDomain(f2Snd,RGhostCellSndMap); 00130 RGhostCellRcv.reinit(RGhostCellRcvMap.size()); 00131 RGhostCellSnd.reinit(RGhostCellSndMap.size()); 00132 assert(RGhostCellRcvMap.size() == elemsInXY); 00133 assert(RGhostCellSndMap.size() == elemsInXY); 00134 00135 FXYSlabId fRFaces(X1+dx,X2,tol); 00136 mesh.tagFacesInDomain(fRFaces,fDeadZone,RIGHT_DEAD_ZONE); 00137 } 00138 00139 }
void LaxFriedrichsMethodMPI::setCommunicationBuffersWithNoOverlap | ( | OrthoMesh & | mesh | ) | [protected] |
Definition at line 10 of file laxfriedrichsmethodmpi.cpp.
00011 { 00012 unsigned elemsInXY = mesh.numElemY()*mesh.numElemZ(); 00013 double dx = mesh.get_dx(); 00014 double tol = dx/4.0; 00015 00016 //If we dont have mesh overlap. each subdomain gets boundary conditions from your neighbors 00017 //and there is no dead zones 00018 if (NetMPI::rank() != 0) 00019 { 00020 double X0 = mesh.getP()[0]; 00021 00022 00023 //With no dead zones each subdomain send the cells at the shared boundary 00024 LGhostCellSndMap.reserve(elemsInXY); 00025 FXYSlabId fSnd(X0,X0+dx,tol); 00026 mesh.getCellsIndicesInDomain(fSnd,LGhostCellSndMap); 00027 00028 //Now each subdomain receive cells values coming from the other side of its boundaries. 00029 //These values were sent by its neighbours domains. 00030 LGhostCellRcvMap.reserve(elemsInXY); 00031 FXYSlabId fRcv(X0,X0,tol); 00032 mesh.getFacesIndicesInDomain(fRcv,LGhostCellRcvMap); 00033 00034 //Initialize buffers to send and get data. 00035 LGhostCellRcv.reinit(LGhostCellRcvMap.size()); 00036 LGhostCellSnd.reinit(LGhostCellSndMap.size()); 00037 } 00038 if (!NetMPI::isLastProcess()) 00039 { 00040 double X0 = mesh.getQ()[0]; 00041 00042 //With no dead zones each subdomain send the cells at the shared boundary 00043 RGhostCellSndMap.reserve(elemsInXY); 00044 FXYSlabId fSnd(X0,X0-dx,tol); 00045 mesh.getCellsIndicesInDomain(fSnd,RGhostCellSndMap); 00046 00047 //Now each subdomain receive cells values coming from the other side of its boundaries. 00048 //These values were sent by its neighbours domains. 00049 RGhostCellRcvMap.reserve(elemsInXY); 00050 FXYSlabId fRcv(X0,X0,tol); 00051 mesh.getFacesIndicesInDomain(fRcv,RGhostCellRcvMap); 00052 00053 //Initialize buffers to send and get data. 00054 RGhostCellRcv.reinit(RGhostCellRcvMap.size()); 00055 RGhostCellSnd.reinit(RGhostCellSndMap.size()); 00056 } 00057 }
void LaxFriedrichsMethodMPI::unitTest | ( | ) |
Definition at line 278 of file laxfriedrichsmethodmpi.cpp.
00279 { 00280 std::ostream &out = NetMPI::getLog(); 00281 out << "\n\nLeft Ghost Rcv\n"; 00282 m_mesh.printCells(LGhostCellRcvMap,out); 00283 out << "\n\nLeft Ghost Snd\n"; 00284 m_mesh.printCells(LGhostCellSndMap,out); 00285 out << "\n\nRight Ghost Rcv\n"; 00286 m_mesh.printCells(RGhostCellRcvMap,out); 00287 out << "\n\nRight Ghost Snd\n"; 00288 m_mesh.printCells(RGhostCellSndMap,out); 00289 00290 }
void LaxFriedrichsMethodMPI::updateDeadZone | ( | ) |
Definition at line 267 of file laxfriedrichsmethodmpi.cpp.
00268 { 00269 if (mesh_overlap)//If no mesh_overlap, we dont have dead zones 00270 { 00271 NetMPI::exchangeDataRedBlack(cLDeadZoneSndMap,cLDeadZoneSnd,cLDeadZoneRcvMap,cLDeadZoneRcv, 00272 cRDeadZoneSndMap,cRDeadZoneSnd,cRDeadZoneRcvMap,cRDeadZoneRcv, 00273 m_cValues,DEAD_ZONE_VALUE); 00274 } 00275 }
void LaxFriedrichsMethodMPI::updateGhostCells | ( | ) |
Definition at line 252 of file laxfriedrichsmethodmpi.cpp.
00253 { 00254 if (mesh_overlap) 00255 NetMPI::exchangeDataRedBlack(LGhostCellSndMap,LGhostCellSnd,LGhostCellRcvMap,LGhostCellRcv, 00256 RGhostCellSndMap,RGhostCellSnd,RGhostCellRcvMap,RGhostCellRcv, 00257 m_cValues,SEND_GHOSTCELL); 00258 else 00259 NetMPI::exchangeDataRedBlack(LGhostCellSndMap,LGhostCellSnd,LGhostCellRcvMap,LGhostCellRcv, 00260 RGhostCellSndMap,RGhostCellSnd,RGhostCellRcvMap,RGhostCellRcv, 00261 m_cValues,m_fValues,SEND_GHOSTCELL); 00262 00263 00264 00265 }
Definition at line 29 of file laxfriedrichsmethodmpi.h.
Indices of cells in the left dead zone
Definition at line 28 of file laxfriedrichsmethodmpi.h.
Indices of cells in the right dead zone
Definition at line 31 of file laxfriedrichsmethodmpi.h.
Definition at line 30 of file laxfriedrichsmethodmpi.h.
Definition at line 38 of file laxfriedrichsmethodmpi.h.
Indices of cells in the right dead zone to receive
Definition at line 37 of file laxfriedrichsmethodmpi.h.
Indices of cells in the right dead zone to send
Definition at line 40 of file laxfriedrichsmethodmpi.h.
Definition at line 39 of file laxfriedrichsmethodmpi.h.
VecTag LaxFriedrichsMethodMPI::fDeadZone [protected] |
Check if a face is in a Dead Zone
Definition at line 47 of file laxfriedrichsmethodmpi.h.
Definition at line 33 of file laxfriedrichsmethodmpi.h.
Definition at line 32 of file laxfriedrichsmethodmpi.h.
Definition at line 35 of file laxfriedrichsmethodmpi.h.
Definition at line 34 of file laxfriedrichsmethodmpi.h.
int LaxFriedrichsMethodMPI::mesh_overlap [private] |
Definition at line 45 of file laxfriedrichsmethodmpi.h.
Definition at line 42 of file laxfriedrichsmethodmpi.h.
Definition at line 41 of file laxfriedrichsmethodmpi.h.
Definition at line 44 of file laxfriedrichsmethodmpi.h.
Definition at line 43 of file laxfriedrichsmethodmpi.h.