LaxFriedrichsMethodMPI Class Reference

#include <laxfriedrichsmethodmpi.h>

Inheritance diagram for LaxFriedrichsMethodMPI:
Inheritance graph
[legend]
Collaboration diagram for LaxFriedrichsMethodMPI:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 LaxFriedrichsMethodMPI (OrthoMesh &mesh, Function3D &fInitU, const VecDouble &cPor, Function3D &fPrescribedU, FaceFluxFunction &flux, double CFL, int mesh_overlap)
virtual ~LaxFriedrichsMethodMPI ()
virtual void iterate (double t, double tEnd)
void updateGhostCells ()
void updateDeadZone ()
void unitTest ()
double negotiateTimeStep (double dt)

Protected Types

enum  FACES_ZONE { ACTIVE_ZONE = 0, LEFT_DEAD_ZONE = 1, RIGHT_DEAD_ZONE = 2 }

Protected Member Functions

void setCommunicationBuffers (OrthoMesh &mesh, int mesh_overlap)
void setCommunicationBuffersWithNoOverlap (OrthoMesh &mesh)

Protected Attributes

VecTag fDeadZone

Private Attributes

VecIndex cLDeadZoneRcvMap
VecDouble cLDeadZoneRcv
VecIndex cLDeadZoneSndMap
VecDouble cLDeadZoneSnd
VecIndex LGhostCellRcvMap
VecDouble LGhostCellRcv
VecIndex LGhostCellSndMap
VecDouble LGhostCellSnd
VecIndex cRDeadZoneRcvMap
VecDouble cRDeadZoneRcv
VecIndex cRDeadZoneSndMap
VecDouble cRDeadZoneSnd
VecIndex RGhostCellRcvMap
VecDouble RGhostCellRcv
VecIndex RGhostCellSndMap
VecDouble RGhostCellSnd
int mesh_overlap

Detailed Description

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.


Member Enumeration Documentation

Enumerator:
ACTIVE_ZONE 
LEFT_DEAD_ZONE 
RIGHT_DEAD_ZONE 

Definition at line 50 of file laxfriedrichsmethodmpi.h.


Constructor & Destructor Documentation

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.

00154 {
00155 
00156 }


Member Function Documentation

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.

00294 {
00295   double dd;
00296   MPI_Allreduce(&dt,&dd,1,MPI_DOUBLE,MPI_MIN,MPI_COMM_WORLD);
00297   return dd;
00298 }

void LaxFriedrichsMethodMPI::setCommunicationBuffers ( OrthoMesh mesh,
int  mesh_overlap 
) [protected]

Initialize everything related to communication among the processes.

Parameters:
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 (  ) 

Member Data Documentation

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.

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.

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.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Sun Apr 8 23:13:14 2012 for CO2INJECTION by  doxygen 1.6.3