53 dim = GridView::dimension, dimWorld = GridView::dimensionworld
61 using PrimaryVariables =
typename SolutionTypes::PrimaryVariables;
63 using ReferenceElements = Dune::ReferenceElements<Scalar, dim>;
66 using MaterialLaw =
typename SpatialParams::MaterialLaw;
73 using IndexSet =
typename GridView::IndexSet;
74 using Intersection =
typename GridView::Intersection;
80 pw = Indices::pressureW,
81 pn = Indices::pressureNw,
82 sw = Indices::saturationW,
83 sn = Indices::saturationNw,
84 wPhaseIdx = Indices::wPhaseIdx,
85 nPhaseIdx = Indices::nPhaseIdx,
86 pressureIdx = Indices::pressureIdx,
87 saturationIdx = Indices::saturationIdx,
88 pressEqIdx = Indices::pressureEqIdx,
89 satEqIdx = Indices::satEqIdx,
93 using Element =
typename GridView::template Codim<0>::Entity;
95 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
96 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
105 ParentType(problem), problem_(problem), velocity_(problem)
107 density_[wPhaseIdx] = 0.;
108 density_[nPhaseIdx] = 0.;
109 viscosity_[wPhaseIdx] = 0.;
110 viscosity_[nPhaseIdx] = 0.;
112 calcVelocityInTransport_ =
getParam<bool>(
"MPFA.CalcVelocityInTransport");
140 const auto element = *problem_.gridView().template begin<0>();
141 FluidState fluidState;
142 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(element));
143 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(element));
144 fluidState.setTemperature(problem_.temperature(element));
145 fluidState.setSaturation(wPhaseIdx, 1.);
146 fluidState.setSaturation(nPhaseIdx, 0.);
147 density_[wPhaseIdx] = FluidSystem::density(fluidState, wPhaseIdx);
148 density_[nPhaseIdx] = FluidSystem::density(fluidState, nPhaseIdx);
149 viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
150 viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
153 velocity_.initialize();
179 return calcVelocityInTransport_;
192 template<
class MultiWriter>
196 velocity_.addOutputVtkFields(writer);
203 Scalar density_[numPhases];
204 Scalar viscosity_[numPhases];
205 bool calcVelocityInTransport_;
224 for (
const auto& vertex : vertices(problem_.gridView()))
226 int vIdxGlobal = problem_.variables().index(vertex);
230 if (interactionVolume.isInnerVolume())
232 auto element1 = interactionVolume.getSubVolumeElement(0);
233 auto element2 = interactionVolume.getSubVolumeElement(1);
234 auto element3 = interactionVolume.getSubVolumeElement(2);
235 auto element4 = interactionVolume.getSubVolumeElement(3);
238 int eIdxGlobal1 = problem_.variables().index(element1);
239 int eIdxGlobal2 = problem_.variables().index(element2);
240 int eIdxGlobal3 = problem_.variables().index(element3);
241 int eIdxGlobal4 = problem_.variables().index(element4);
244 CellData& cellData1 = problem_.variables().cellData(eIdxGlobal1);
245 CellData& cellData2 = problem_.variables().cellData(eIdxGlobal2);
246 CellData& cellData3 = problem_.variables().cellData(eIdxGlobal3);
247 CellData& cellData4 = problem_.variables().cellData(eIdxGlobal4);
249 velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume, cellData1, cellData2,
256 for (
int elemIdx = 0; elemIdx < 2 * dim; elemIdx++)
258 bool isOutside =
false;
259 for (
int fIdx = 0; fIdx < dim; fIdx++)
261 int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, fIdx);
262 if (interactionVolume.isOutsideFace(intVolFaceIdx))
273 int eIdxGlobal = problem_.variables().index(interactionVolume.getSubVolumeElement(elemIdx));
275 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
277 velocity_.calculateBoundaryInteractionVolumeVelocity(interactionVolume, cellData, elemIdx);
299 int numVertices = intersection.geometry().corners();
301 auto elementI = intersection.inside();
302 auto elementJ = intersection.outside();
304 int eIdxGlobalI = problem_.variables().index(elementI);
305 int eIdxGlobalJ = problem_.variables().index(elementJ);
307 CellData& cellDataJ = problem_.variables().cellData(eIdxGlobalJ);
309 const auto referenceElement = ReferenceElements::general(elementI.type());
311 int indexInInside = intersection.indexInInside();
312 int indexInOutside = intersection.indexInOutside();
314 Dune::FieldVector<CellData, 4> cellDataTemp;
316 for (
int vIdx = 0; vIdx < numVertices; vIdx++)
318 int localVertIdx = referenceElement.subEntity(indexInInside, dim - 1, vIdx, dim);
320 int vIdxGlobal = problem_.variables().index(elementI.template subEntity<dim>(localVertIdx));
324 if (interactionVolume.isInnerVolume())
327 auto element1 = interactionVolume.getSubVolumeElement(0);
328 auto element2 = interactionVolume.getSubVolumeElement(1);
329 auto element3 = interactionVolume.getSubVolumeElement(2);
330 auto element4 = interactionVolume.getSubVolumeElement(3);
334 eIdxGlobal[0] = problem_.variables().index(element1);
335 eIdxGlobal[1] = problem_.variables().index(element2);
336 eIdxGlobal[2] = problem_.variables().index(element3);
337 eIdxGlobal[3] = problem_.variables().index(element4);
340 cellDataTemp[0] = problem_.variables().cellData(eIdxGlobal[0]);
341 cellDataTemp[1] = problem_.variables().cellData(eIdxGlobal[1]);
342 cellDataTemp[2] = problem_.variables().cellData(eIdxGlobal[2]);
343 cellDataTemp[3] = problem_.variables().cellData(eIdxGlobal[3]);
345 velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume, cellDataTemp[0], cellDataTemp[1],
348 for (
int i = 0; i < 4; i++)
350 if (eIdxGlobal[i] == eIdxGlobalI)
352 cellData.fluxData().setVelocity(wPhaseIdx, indexInInside,
353 cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInInside));
354 cellData.fluxData().setVelocity(nPhaseIdx, indexInInside,
355 cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInInside));
356 cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside,
357 cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInInside));
358 cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside,
359 cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInInside));
361 else if (eIdxGlobal[i] == eIdxGlobalJ)
363 cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside,
364 cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInOutside));
365 cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside,
366 cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInOutside));
367 cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside,
368 cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInOutside));
369 cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside,
370 cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInOutside));
375 cellData.fluxData().setVelocityMarker(indexInInside);
376 cellDataJ.fluxData().setVelocityMarker(indexInOutside);
390 auto element = intersection.inside();
393 int isIndex = intersection.indexInInside();
396 const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
398 BoundaryTypes bcType;
400 problem_.boundaryTypes(bcType, intersection);
401 PrimaryVariables boundValues(0.0);
403 if (bcType.isDirichlet(pressEqIdx))
405 problem_.dirichlet(boundValues, intersection);
408 const GlobalPosition& globalPosI = element.geometry().center();
411 const GlobalPosition& globalPosJ = intersection.geometry().center();
414 Scalar lambdaWI = cellData.mobility(wPhaseIdx);
415 Scalar lambdaNwI = cellData.mobility(nPhaseIdx);
418 Scalar pcI = cellData.capillaryPressure();
421 GlobalPosition distVec = globalPosJ - globalPosI;
424 Scalar dist = distVec.two_norm();
428 DimMatrix meanPermeability(0);
430 problem_.spatialParams().meanK(meanPermeability, problem_.spatialParams().intrinsicPermeability(element));
432 Dune::FieldVector<Scalar, dim> permeability(0);
433 meanPermeability.mv(unitOuterNormal, permeability);
437 if (bcType.isDirichlet(satEqIdx))
439 switch (saturationType_)
443 satW = boundValues[saturationIdx];
448 satW = 1 - boundValues[saturationIdx];
455 satW = cellData.saturation(wPhaseIdx);
458 Scalar pressBound = boundValues[pressureIdx];
459 Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW);
462 Scalar pressWBound = 0;
463 Scalar pressNwBound = 0;
464 if (pressureType_ == pw)
466 pressWBound = pressBound;
467 pressNwBound = pressBound + pcBound;
469 else if (pressureType_ == pn)
471 pressWBound = pressBound - pcBound;
472 pressNwBound = pressBound;
475 Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW)
476 / viscosity_[wPhaseIdx];
477 Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW)
478 / viscosity_[nPhaseIdx];
480 Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex);
481 Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex);
484 potentialDiffW = (cellData.pressure(wPhaseIdx) - pressWBound);
485 potentialDiffNw = (cellData.pressure(nPhaseIdx) - pressNwBound);
487 potentialDiffW += density_[wPhaseIdx] * (distVec * problem_.gravity());
488 potentialDiffNw += density_[nPhaseIdx] * (distVec * problem_.gravity());
491 cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, potentialDiffW);
492 cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, potentialDiffNw);
495 Scalar lambdaW = (potentialDiffW > 0.) ? lambdaWI : lambdaWBound;
496 lambdaW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialDiffW, 0.0, 1.0e-30)) ? 0.5 * (lambdaWI + lambdaWBound) : lambdaW;
497 Scalar lambdaNw = (potentialDiffNw > 0.) ? lambdaNwI : lambdaNwBound;
498 lambdaNw = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialDiffNw, 0.0, 1.0e-30)) ? 0.5 * (lambdaNwI + lambdaNwBound) : lambdaNw;
501 Scalar scalarPerm = permeability.two_norm();
504 Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
505 Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
509 Scalar areaScaling = (unitOuterNormal * distVec);
511 Scalar gravityTermW = (problem_.gravity() * distVec) * density_[wPhaseIdx] * areaScaling;
512 Scalar gravityTermNw = (problem_.gravity() * distVec) * density_[nPhaseIdx] * areaScaling;
515 switch (pressureType_)
519 velocityW *= lambdaW * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermW);
520 velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermNw)
521 + 0.5 * (lambdaNwI + lambdaNwBound) * scalarPerm * (pcI - pcBound) / dist;
526 velocityW *= lambdaW * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermW)
527 - 0.5 * (lambdaWI + lambdaWBound) * scalarPerm * (pcI - pcBound) / dist;
528 velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermNw);
534 cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
535 cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
536 cellData.fluxData().setVelocityMarker(isIndex);
540 else if (bcType.isNeumann(pressEqIdx))
542 problem_.neumann(boundValues, intersection);
544 Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
545 Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
547 velocityW *= boundValues[wPhaseIdx];
548 velocityNw *= boundValues[nPhaseIdx];
550 velocityW /= density_[wPhaseIdx];
551 velocityNw /= density_[nPhaseIdx];
554 cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, boundValues[wPhaseIdx]);
555 cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, boundValues[nPhaseIdx]);
557 cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
558 cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
559 cellData.fluxData().setVelocityMarker(isIndex);
563 DUNE_THROW(Dune::NotImplemented,
"No valid boundary condition type defined for pressure equation!");