00001 #include "mixedhybridcompositionalfull.h"
00002 #include "numericmethods.h"
00003 #include "hdf5orthowriter.h"
00004
00005
00006 MixedHybridCompositionalFull::MixedHybridCompositionalFull(OrthoMesh &mesh,Function3D &fPInit,Function3D &fPrescribedVelocities, Function3D &fPrescribedPression, const VecDouble &K, const VecDouble &vPor,Function1D &fMobT,Function1D &fRelMobilities,double grav, double dt,FlashCompositional &flash,LinearSolver &solver,int debugLevel,bool bCheckNoBC)
00007 :MixedHybridCompositional(mesh,fPInit,fPrescribedVelocities, fPrescribedPression, K, vPor,fMobT,fRelMobilities,grav, dt,flash,solver,debugLevel, bCheckNoBC)
00008 {
00009 m_vDvDm.reinit(mesh.numCells(),2);
00010 m_vC.reinit(mesh.numCells(),2);
00011 m_vMobT.reinit(mesh.numCells());
00012 m_vMobRel.reinit(mesh.numCells());
00013
00014 }
00015
00016
00017
00018
00019 void MixedHybridCompositionalFull::iterate(TransportBase &trans)
00020 {
00021 this->assemblySystem(m_A,m_B,m_dt,m_sol,m_vK,m_vPor,m_flash,m_fMobT,m_fFracFlux,m_grav);
00022
00023 VecDouble PAnt=m_sol;
00024
00025 m_solver.solve(m_A,m_sol,m_B);
00026
00027 Point3D p(5,50,50);
00028 OrthoMesh::Cell_It cell = m_mesh.getCellAt(p);
00029
00030
00031
00032 this->getNormalVdtFromPressure(m_Vq,m_mesh,m_bc,m_vK,m_sol,m_vMobT);
00033
00034 }
00035
00036 using NumericMethods::_div;
00037
00038
00039
00040
00041
00042
00043
00044 void MixedHybridCompositionalFull::assemblySystem(SparseMatrix<double> &A,VecDouble &B, double dt, const VecDouble &vP, const VecDouble &vK, const VecDouble &vPor, FlashCompositional &flash, GeneralFunctionInterface &fMobT, GeneralFunctionInterface &fRelMobilities,double grav)
00045 {
00046 assert((flash.numPhases() -1) == fRelMobilities.getImageDim());
00047 assert(fMobT.getDomainDim() == flash.numPhases()-1);
00048 assert(fMobT.getImageDim() == 1);
00049 assert(fRelMobilities.getDomainDim() == flash.numPhases()-1);
00050
00051 static VecDouble totalComponents(flash.numComponents());
00052 static VecDouble dv_dm(flash.numComponents());
00053 static VecDouble phasesVol(flash.numPhases());
00054 static VecDouble phasesDensities(flash.numPhases());
00055 static VecDouble phasesViscosities(flash.numPhases());
00056
00057 double maxStE=0;
00058
00059
00060
00061
00062 static VecDouble vS(flash.numPhases()-1);
00063
00064
00065
00066
00067
00068 static FlashData data(flash.numPhases(),flash.numComponents());
00069
00070
00071
00072 OrthoMesh::Cell_It cell = m_mesh.begin_cell();
00073 Index nCells = m_mesh.numCells();
00074
00075
00076 A=0.0;
00077 B=0.0;
00078
00079
00080 double BetaG_dt;
00081 double St;
00082 for (Index cellIndex=0;cellIndex < nCells; cellIndex++,cell++)
00083 {
00084
00085 flash.flash(cellIndex,data);
00086 double P=vP(cellIndex);
00087
00088 flash.getPhasesVolume(P,data,phasesVol);
00089 St=phasesVol.l1_norm();
00090
00091
00092 if (fabs(1-St) > maxStE) maxStE = fabs(1-St);
00093
00094 BetaG_dt=vPor(cellIndex)*flash.getFluidCompressibility(P,data)/(dt);
00095 if (BetaG_dt < -0.0)
00096 {
00097 printf("Error BetaG_dt = %g\n",BetaG_dt);
00098 data.print();
00099 abort();
00100 }
00101 A.add(cellIndex,cellIndex,BetaG_dt);
00102 B(cellIndex)+=BetaG_dt*P+vPor(cellIndex)*(St-1.0)/dt;
00103
00104
00105
00106
00107
00108
00109 flash.getPhasesViscosities(P,data,phasesViscosities);
00110 fMobT.setParameters(phasesViscosities);
00111 fRelMobilities.setParameters(phasesViscosities);
00112
00113
00114
00115
00116
00117
00118
00119
00120 for (unsigned k=0;k<vS.size();k++)
00121 vS(k) = phasesVol(k)/St;
00122 m_vMobT(cellIndex)=fMobT(vS);
00123 m_vMobRel(cellIndex)=fRelMobilities(vS);
00124
00125
00126 data.getTotalComponentsMoles(totalComponents);
00127
00128
00129 flash.getTotalVolumeDerivatives(P,data,dv_dm);
00130
00131 m_vDvDm(cellIndex,0)=dv_dm(0);
00132 m_vDvDm(cellIndex,1)=dv_dm(1);
00133 m_vC(cellIndex,0)=_div(data.getMoles(0,0),phasesVol(0))*fRelMobilities(vS)*fMobT(vS);
00134 m_vC(cellIndex,1)=( _div(data.getMoles(0,1), phasesVol(0)) * fRelMobilities(vS) +
00135 _div(data.getMoles(1,1), phasesVol(1))*(1-fRelMobilities(vS)))*fMobT(vS);
00136
00137
00138
00139
00140
00141 }
00142
00143
00144
00145
00146
00147
00148 OrthoMesh::Face_It face = m_mesh.begin_face();
00149 unsigned nFaces = m_mesh.numFaces();
00150
00151
00152
00153
00154
00155 for (unsigned faceIndex=0;faceIndex < nFaces; faceIndex++,face++)
00156 {
00157 unsigned c1,c2;
00158 face->getAdjCellIndices(c1,c2);
00159
00160
00161 if (!face->at_boundary())
00162 {
00163 double inv_dx2 = m_vInvH2(face->getNormalOrientation());
00164
00165
00166 double K1 = vK(c1)*m_vC(c1,0);
00167 double K2 = vK(c2)*m_vC(c2,0);
00168 double Ceff=2*_div(K1*K2,(K1+K2));
00169 A.add(c1,c1, +m_vDvDm(c1,0)*Ceff * inv_dx2);
00170 A.add(c1,c2, -m_vDvDm(c1,0)*Ceff * inv_dx2);
00171 A.add(c2,c2, +m_vDvDm(c2,0)*Ceff * inv_dx2);
00172 A.add(c2,c1, -m_vDvDm(c2,0)*Ceff * inv_dx2);
00173
00174
00175 K1 = vK(c1)*m_vC(c1,1);
00176 K2 = vK(c2)*m_vC(c2,1);
00177 Ceff=2*_div(K1*K2,(K1+K2));
00178 A.add(c1,c1, +m_vDvDm(c1,1)*Ceff * inv_dx2);
00179 A.add(c1,c2, -m_vDvDm(c1,1)*Ceff * inv_dx2);
00180 A.add(c2,c2, +m_vDvDm(c2,1)*Ceff * inv_dx2);
00181 A.add(c2,c1, -m_vDvDm(c2,1)*Ceff * inv_dx2);
00182 }
00183 }
00184
00185
00186 HybridFaceBC::iterator bcEnd = m_bc.end();
00187 for(HybridFaceBC::iterator bcIt = m_bc.begin();bcIt!=bcEnd;bcIt++)
00188 {
00189 OrthoMesh::Face_It face = bcIt->face;
00190 assert(face->at_boundary());
00191
00192 unsigned c1,c2;
00193 face->getAdjCellIndices(c1,c2);
00194
00195 if (bcIt->bcType == Dirichlet)
00196 {
00197 double inv_dx2 = m_vInvH2(face->getNormalOrientation());
00198 double c = (c1 != OrthoMesh::invalidIndex()) ? c1 : c2;
00199 double Coeff = +2*vK(c)*(m_vC(c,0)*m_vDvDm(c,0) + m_vC(c,1)*m_vDvDm(c,1))*inv_dx2;
00200
00201 A.add(c,c, Coeff);
00202 B(c) += Coeff*bcIt->value;
00203 }
00204 else
00205 {
00206 if (bcIt->value != 0.0)
00207 {
00208 throw new Exception("The fully compositional model only accept null newmann condition");
00209
00210 }
00211 if (c1 != OrthoMesh::invalidIndex())
00212 B(c1) += -bcIt->value;
00213 else
00214 B(c2) += +bcIt->value;
00215 }
00216 }
00217
00218 HDF5OrthoWriter::getHDF5OrthoWriter().setVariable("St_Error",maxStE);
00219 maxStE=0;
00220
00221 }
00222
00223
00224
00225
00226
00227
00228
00229 void MixedHybridCompositionalFull::getNormalVdtFromPressure(VecDouble &Vq,OrthoMesh &mesh,HybridFaceBC &bc,const VecDouble &K,const VecDouble &vP,const VecDouble &vMobT)
00230 {
00231 assert(Vq.size() == mesh.numFaces());
00232 assert(vP.size() == mesh.numCells());
00233 assert(vMobT.size() == mesh.numCells());
00234 assert(K.size() == mesh.numCells());
00235
00236
00237
00238 OrthoMesh::Face_It face = mesh.begin_face();
00239 OrthoMesh::Face_It endf = mesh.end_face();
00240
00241 using NumericMethods::_div;
00242
00243 for (;face!=endf;face++)
00244 {
00245 if (!face->at_boundary())
00246 {
00247 unsigned c1,c2;
00248 face->getAdjCellIndices(c1,c2);
00249 double K1 = K(c1)*vMobT(c1);
00250 double K2 = K(c2)*vMobT(c2);
00251 double Keff = 2*K1*K2/(K1+K2)*face->areaPerCellVol();
00252 Vq(face->index()) = - Keff * (vP(c2) - vP(c1));
00253
00254
00255 }
00256 }
00257
00258
00259
00260 HybridFaceBC::iterator bcEnd = bc.end();
00261 for(HybridFaceBC::iterator bcIt = bc.begin();bcIt!=bcEnd;bcIt++)
00262 {
00263 OrthoMesh::Face_It face = bcIt->face;
00264 assert(face->at_boundary());
00265
00266 unsigned c1,c2;
00267 face->getAdjCellIndices(c1,c2);
00268
00269 if (bcIt->bcType == Dirichlet)
00270 {
00271 if (c1 != OrthoMesh::invalidIndex())
00272 {
00273 double Keff = 2*K(c1)*vMobT(c1)*face->areaPerCellVol();
00274 Vq(face->index()) = - Keff*(bcIt->value - vP(c1));
00275
00276 }
00277 else
00278 {
00279 double Keff = 2*K(c2)*vMobT(c2)*face->areaPerCellVol();
00280 Vq(face->index()) = Keff*(bcIt->value - vP(c2));
00281
00282 }
00283 }
00284 else
00285 {
00286 if (c1 != OrthoMesh::invalidIndex())
00287 Vq(face->index()) = bcIt->value/face->area();
00288 else
00289 Vq(face->index()) = bcIt->value/face->area();
00290 }
00291 }
00292
00293 }
00294
00295
00296 MixedHybridCompositionalFull::~MixedHybridCompositionalFull()
00297 {
00298
00299 }
00300
00301
00302
00303
00304
00305 void MixedHybridCompositionalFull::getTotalMassFluxFromPressure(VecDouble &Vq,OrthoMesh &mesh,const HybridFaceBC &bc,const VecDouble &K,const VecDouble &vP,const Matrix &MC)
00306 {
00307 assert(Vq.size() == mesh.numFaces());
00308 assert(vP.size() == mesh.numCells());
00309 assert(K.size() == mesh.numCells());
00310
00311
00312
00313 OrthoMesh::Face_It face = mesh.begin_face();
00314 OrthoMesh::Face_It endf = mesh.end_face();
00315
00316
00317
00318
00319 for (;face!=endf;face++)
00320 {
00321 if (!face->at_boundary())
00322 {
00323 unsigned c1,c2;
00324 face->getAdjCellIndices(c1,c2);
00325
00326
00327 double K1 = K(c1)*MC(c1,0);
00328 double K2 = K(c2)*MC(c2,0);
00329 double K3 = K(c1)*MC(c1,1);
00330 double K4 = K(c2)*MC(c2,1);
00331 double Keff = 2*(_div(K1*K2,K1+K2) + _div(K3*K4,K3+K4)) *face->areaPerCellVol();
00332 Vq(face->index()) = - Keff * (vP(c2) - vP(c1));
00333 }
00334 }
00335
00336
00337
00338 HybridFaceBC::const_iterator bcEnd = bc.end();
00339 for(HybridFaceBC::const_iterator bcIt = bc.begin();bcIt!=bcEnd;bcIt++)
00340 {
00341 OrthoMesh::Face_It face = bcIt->face;
00342 assert(face->at_boundary());
00343
00344 unsigned c1,c2;
00345 face->getAdjCellIndices(c1,c2);
00346
00347 if (bcIt->bcType == Dirichlet)
00348 {
00349 if (c1 != OrthoMesh::invalidIndex())
00350 {
00351 double Keff = 2*K(c1)*(MC(c1,0) + MC(c1,1))*face->areaPerCellVol();
00352 Vq(face->index()) = - Keff*(bcIt->value - vP(c1));
00353
00354 }
00355 else
00356 {
00357 double Keff = 2*K(c2)*(MC(c2,0) + MC(c2,1))*face->areaPerCellVol();
00358 Vq(face->index()) = Keff*(bcIt->value - vP(c2));
00359
00360 }
00361 }
00362 else
00363 {
00364 if (c1 != OrthoMesh::invalidIndex())
00365 Vq(face->index()) = bcIt->value/face->area();
00366 else
00367 Vq(face->index()) = bcIt->value/face->area();
00368 }
00369 }
00370
00371
00372 }
00373
00374
00375
00376
00377
00378 void MixedHybridCompositionalFull::printOutput()
00379 {
00380 MixedHybridCompositional::printOutput();
00381
00382 if (_debugLevel > 1)
00383 {
00384 Matrix VelM(m_mesh.numVertices(),3);
00385 VecDouble Vf(m_mesh.numFaces());
00386 VecDouble Vv(m_mesh.numVertices());
00387 VecDouble Vc(m_mesh.numCells());
00388 HDF5OrthoWriter &hdf5 = HDF5OrthoWriter::getHDF5OrthoWriter();
00389
00390
00391
00392
00393
00394 }
00395
00396
00397
00398
00399 }
00400
00401
00402 void MixedHybridCompositionalFull::getNormalMassFluxAtFaces(VecDouble &vFNC)
00403 {
00404 getTotalMassFluxFromPressure(vFNC,m_mesh,m_bc,m_vK,m_sol,m_vC);
00405 }