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