00001 #include "compdiffusivestep.h"
00002 #include "numericmethods.h"
00003 #include "hdf5orthowriter.h"
00004
00005 using NumericMethods::_div;
00006
00007 CompDiffusiveStep::CompDiffusiveStep(OrthoMesh &mesh, Function3D &fPrescribedPressure, Function3D &fTransportBC,const VecDouble &K, const VecDouble &vPor,Function1D &fMobPc, Function1D &DfPc,FlashCompositional &flash,LinearSolver &solver)
00008 :m_mesh(mesh),m_solver(solver),m_flash(flash),m_vK(K),m_vPor(vPor),m_fMobPc(fMobPc),m_DfPc(DfPc)
00009 {
00010 m_vCoeff.reinit(mesh.numCells());
00011 m_vCoeff2.reinit(mesh.numCells());
00012 m_sol.reinit(mesh.numCells());
00013 m_B.reinit(mesh.numCells());
00014
00015 m_vSaq.reinit(mesh.numCells());
00016 m_vSaqPrev.reinit(mesh.numCells());
00017
00018
00019
00020 buildSparsityPattern(mesh,m_sparsePattern);
00021 m_A.reinit(m_sparsePattern);
00022 m_cV.reinit(mesh.numCells());
00023 m_vV.reinit(mesh.numVertices());
00024
00025 }
00026
00027 void CompDiffusiveStep::setSaqBC(VecIncAccess<FlashBC> &flashbc, ScalarBC &swbc,const Function3D &fPressureBC, const Function3D &fTransBC,FlashCompositional &flash)
00028 {
00029 assert(flash.numPhases() == 2);
00030 assert(fTransBC.getImageDim() == flash.numComponents());
00031 unsigned ncmps = flash.numComponents();
00032
00033 VecDouble cmps(flash.numComponents());
00034 VecDouble phasesVol(flash.numPhases());
00035 FlashData flashData(flash.numPhases(),flash.numComponents());
00036 flashData.allocateOwnMemory();
00037
00038 OrthoMesh::Face_It face = m_mesh.begin_face();
00039 OrthoMesh::Face_It endf = m_mesh.end_face();
00040 for (;face!=endf;face++)
00041 {
00042 if (face->at_boundary())
00043 {
00044 Point3D p = face->barycenter();
00045 if (fTransBC.isInDomain(p))
00046 {
00047 assert(fPressureBC.isInDomain(p));
00048 for (unsigned i=0;i<ncmps;i++)
00049 {
00050 cmps(i)=fTransBC(p,i);
00051 }
00052 double P = fPressureBC(p);
00053 flash.flash(P,cmps,flashData);
00054 flash.getPhasesVolume(P,flashData,phasesVol);
00055 double Saq = phasesVol(0)/(phasesVol(1)+phasesVol(0));
00056 FlashBC _flashBC;
00057 _ScalarBC _sBC;
00058 _flashBC.Saq=Saq;
00059 _sBC.value=Saq;
00060 _sBC.face=face;
00061 swbc.push_back(_sBC);
00062 flashbc.push_back(face->index(),_flashBC);
00063 }
00064 }
00065 }
00066 }
00067
00068
00069
00070 void CompDiffusiveStep::iterate(double dt)
00071 {
00072 const VecDouble &vP=m_flash.getDynamicModule().getPressureAtCells();
00073 TransportBase &trans = m_flash.getTransportModule();
00074 assert(m_flash.numPhases()==2);
00075
00076 static VecDouble phasesVol(m_flash.numPhases());
00077
00078
00079
00080
00081
00082 static FlashData data(m_flash.numPhases(),m_flash.numComponents());
00083
00084
00085 Index nCells = m_mesh.numCells();
00086 double cellVol=m_mesh.begin_cell()->volume();
00087
00088
00089 m_A=0.0;
00090 m_B=0.0;
00091
00092 for (Index cellIndex=0;cellIndex < nCells; cellIndex++)
00093 {
00094
00095 m_flash.flash(cellIndex,data);
00096 double P=vP(cellIndex);
00097 m_flash.getPhasesVolume(P,data,phasesVol);
00098
00099
00100 double Saq=phasesVol(0)/(phasesVol(1)+phasesVol(0));
00101 m_vSaqPrev(cellIndex)=Saq;
00102 double por=m_vPor(cellIndex);
00103
00104 double molarVol;
00105 if (fabs(Saq) == 0.0)
00106 molarVol=1.2733e-4;
00107 else
00108 molarVol = Saq/data.getPhaseTotalMoles(0);
00109
00110 m_A.add(cellIndex,cellIndex,molarVol*por*cellVol/dt);
00111 m_B(cellIndex)+=molarVol*por*Saq/dt*cellVol;
00112
00113 m_vCoeff(cellIndex)=-m_vK(cellIndex)*m_DfPc(Saq)*m_fMobPc(Saq);
00114 m_vCoeff2(cellIndex)=m_vCoeff(cellIndex)*molarVol;
00115 }
00116
00117
00118 MixedHybridBase::assemblySystem(m_A,m_B,m_mesh,m_swBC,m_vCoeff2);
00119
00120
00121 m_solver.solve(m_A,m_vSaq,m_B);
00122 unsigned n_components = m_flash.numComponents();
00123
00124 ArrayOfVecDouble &vSol = trans.getSolutionAtCells();
00125
00126
00127
00128
00129 for (unsigned cmp=0;cmp<n_components;cmp++)
00130 {
00131 OrthoMesh::Face_It face = m_mesh.begin_face();
00132 OrthoMesh::Face_It end = m_mesh.end_face();
00133 Index c1,c2;
00134 FlashData data1(m_flash.numPhases(),m_flash.numComponents());
00135 FlashData data2(m_flash.numPhases(),m_flash.numComponents());
00136 VecIncAccess<FlashBC>::iterator it=m_flashBC.begin();
00137 for (;face!=end;face++)
00138 {
00139 if (!face->at_boundary())
00140 {
00141 face->getAdjCellIndices(c1,c2);
00142 double Saq1=m_vSaqPrev(c1);
00143 double Saq2=m_vSaqPrev(c2);
00144 m_flash.flash(c1,data1);
00145 m_flash.flash(c2,data2);
00146 double Kflux1 = m_vCoeff(c1)*(_div(data1.getMoles(0,cmp),Saq1) - _div(data1.getMoles(1,cmp),(1-Saq1)));
00147 double Kflux2 = m_vCoeff(c2)*( _div(data2.getMoles(0,cmp),Saq2) - _div(data2.getMoles(1,cmp),(1-Saq2)));
00148 double flux = - 2*_div(Kflux1*Kflux2, (Kflux1+Kflux2))*(m_vSaq(c2)-m_vSaq(c1))*face->areaPerCellVol();
00149
00150
00151
00152
00153 vSol(c1,cmp)-=flux/m_vPor(c1)*dt*face->areaPerCellVol();
00154 vSol(c2,cmp)+=flux/m_vPor(c2)*dt*face->areaPerCellVol();
00155 }
00156 else
00157 {
00158 Index faceIndex = face->index();
00159 const FlashBC *flash_bc = it.inc_search(faceIndex);
00160 if (flash_bc)
00161 {
00162 abort();
00163 face->getAdjCellIndices(c1,c2);
00164 double Saq = flash_bc->Saq;
00165 if (c1 != OrthoMesh::INVALID_INDEX)
00166 {
00167 m_flash.flash(c1,data1);
00168 double Kflux = m_vCoeff(c1)*(_div(data1.getMoles(0,cmp),m_vSaqPrev(c1)) - _div(data1.getMoles(1,cmp),1-m_vSaqPrev(c1)));
00169 double flux= -2*Kflux*(Saq-m_vSaq(c1))*face->areaPerCellVol();
00170 vSol(c1,cmp)-=flux/m_vPor(c1)*dt*face->areaPerCellVol();
00171 }
00172 else
00173 {
00174 m_flash.flash(c2,data2);
00175 double Kflux = m_vCoeff(c2)*(_div(data2.getMoles(0,cmp),m_vSaqPrev(c2)) - _div(data2.getMoles(1,cmp),1-m_vSaqPrev(c2)));
00176 double flux= -2*Kflux*(m_vSaq(c2) - Saq)*face->areaPerCellVol();
00177 vSol(c2,cmp)+=flux/m_vPor(c2)*dt*face->areaPerCellVol();
00178 }
00179 }
00180 }
00181 }
00182 }
00183 }
00184
00185
00186 CompDiffusiveStep::~CompDiffusiveStep()
00187 {
00188
00189 }